ElasticSearch:商品SKU+SPU實現join查詢,設計及優化

文章目錄

  • 一、SPU+SKU
    • 1、商品SPU和SKU
    • 2、SPU和SKU的關系
    • 3、實現SPU+SKU父子嵌套查詢
      • 1. **嵌套對象(Nested Objects)**
      • 2. **父子關系(Parent-Child)**
      • 3. **應用層關聯(Application-Side Join)**(推薦)
      • 4. **預連接數據(Denormalization)**(推薦)
      • 方案對比
      • 優化建議

一、SPU+SKU

1、商品SPU和SKU

每個店鋪中會包含多個商品,每個商品會有多個規格。

紅框上面的部分是商品的SPU(Standard Product Unit 標準產品單位),SPU是商品信息聚合的最小單位,是一組可復用、易檢索的標準化信息的集合,該集合描述了一個產品的特性。這里會選擇對應店鋪的名稱,填入商品編號、商品名稱、上架狀態、定時上架時間、商品標簽、商品圖片等信息。

下面紅色的框體是商品的SKU(stock keeping unit 庫存量單位),SKU即庫存進出計量的單位, 可以是以件、盒、托盤等為單位,SKU是物理上不可分割的最小存貨單元。包括商品顏色、商品存儲容量、商品價格、商品剩余數量。

在這里插入圖片描述

2、SPU和SKU的關系

如圖所示,一個店鋪會對應多個商品的SPU。同時一個商品的SPU會包含多個商品SKU,以手機為例,一款iPhone12手機就是SPU,如果消費者需要購買該手機的時候,還需要選擇手機顏色、內存容量,在商家這邊還要查看商品的庫存是否足夠。因此,一個商品SPU會對
應多個商品SKU的描述。
在這里插入圖片描述
如果我們建立數據庫表的時候會將店鋪、商品SPU和商品SKU建立三張表,通過主外鍵的關系關聯。
如果mysql的數據同步到ES中,用戶進行搜索的時候,應該怎么實現呢?

在 Elasticsearch(ES)中實現關聯查詢(join)的方式與傳統關系型數據庫不同,因為 ES 是分布式搜索引擎,其設計初衷并非處理復雜關聯。以下是幾種常見的 ES 關聯實現方法:

3、實現SPU+SKU父子嵌套查詢

1. 嵌套對象(Nested Objects)

場景:SPU 與 SKU 強關聯,查詢時需同時檢索。
示例:一款手機(SPU)有多個顏色和配置(SKU)。

映射與數據

PUT /products
{"mappings": {"properties": {"spu_id": {"type": "keyword"},"spu_name": {"type": "text"},"brand": {"type": "keyword"},"skus": {"type": "nested",  // 嵌套類型"properties": {"sku_id": {"type": "keyword"},"color": {"type": "keyword"},"size": {"type": "keyword"},"price": {"type": "double"},"stock": {"type": "integer"}}}}}
}PUT /products/_doc/1
{"spu_id": "SPU001","spu_name": "蘋果 iPhone 14","brand": "Apple","skus": [{"sku_id": "SKU001","color": "黑色","size": "128GB","price": 5999.00,"stock": 100},{"sku_id": "SKU002","color": "藍色","size": "256GB","price": 6799.00,"stock": 50}]
}

查詢示例

  • 需求:查找所有品牌為 Apple 且有藍色 256GB 的手機。
  • 實現
{"query": {"bool": {"must": [{"term": {"brand": "Apple"}},{"nested": {  // 嵌套查詢"path": "skus","query": {"bool": {"must": [{"term": {"skus.color": "藍色"}},{"term": {"skus.size": "256GB"}}]}}}}]}}
}

2. 父子關系(Parent-Child)

場景:SPU 與 SKU 生命周期獨立,需靈活管理(如動態添加 SKU)。
示例:一款手機(SPU)的 SKU 庫存需實時更新。

映射與數據

PUT /products
{"mappings": {"properties": {"join_field": {"type": "join","relations": {"spu": "sku"  // 定義父子關系}}}}
}// 索引 SPU(父文檔)
PUT /products/_doc/SPU001
{"spu_id": "SPU001","name": "蘋果 iPhone 14","brand": "Apple","join_field": {"name": "spu"}
}// 索引 SKU(子文檔)
PUT /products/_doc/SKU001?routing=SPU001  // 必須使用父 ID 作為路由
{"sku_id": "SKU001","color": "黑色","size": "128GB","price": 5999.00,"stock": 100,"join_field": {"name": "sku", "parent": "SPU001"}
}PUT /products/_doc/SKU002?routing=SPU001
{"sku_id": "SKU002","color": "藍色","size": "256GB","price": 6799.00,"stock": 50,"join_field": {"name": "sku", "parent": "SPU001"}
}

查詢示例

  • 需求:查找價格低于 6000 的 SKU 所屬的 SPU 信息。
  • 實現
{"query": {"has_child": {"type": "sku","query": {"range": {"price": {"lt": 6000}}},"inner_hits": {}  // 返回匹配的子文檔}}
}

3. 應用層關聯(Application-Side Join)(推薦)

場景:SPU 和 SKU 存儲在不同索引,需跨索引關聯。
示例:SPU 數據在 spu_index,SKU 數據在 sku_index

數據結構

// SPU 索引
PUT /spu_index/_doc/SPU001
{"spu_id": "SPU001","name": "蘋果 iPhone 14","brand": "Apple","category": "手機","description": "2023年新款智能手機..."
}// SKU 索引
PUT /sku_index/_doc/SKU001
{"sku_id": "SKU001","spu_id": "SPU001",  // 關聯字段"color": "黑色","size": "128GB","price": 5999.00,"stock": 100,"sales": 2000
}

查詢流程(Python)

from elasticsearch import Elasticsearches = Elasticsearch()# 1. 查詢手機分類下的所有 SPU
spu_result = es.search(index="spu_index",body={"query": {"term": {"category": "手機"}},"_source": ["spu_id", "name", "brand"]},size=100
)# 2. 提取 SPU IDs
spu_ids = [hit["_source"]["spu_id"] for hit in spu_result["hits"]["hits"]]# 3. 批量查詢 SKU(按價格排序)
sku_result = es.search(index="sku_index",body={"query": {"terms": {"spu_id": spu_ids}},"sort": {"price": "asc"},"_source": ["spu_id", "color", "size", "price"]},size=1000
)# 4. 應用層組裝結果(SPU + 最低價格 SKU)
spu_sku_map = {}
for sku in sku_result["hits"]["hits"]["_source"]:spu_id = sku["spu_id"]if spu_id not in spu_sku_map or sku["price"] < spu_sku_map[spu_id]["price"]:spu_sku_map[spu_id] = sku# 5. 合并 SPU 和 SKU 信息
merged_result = []
for spu_hit in spu_result["hits"]["hits"]:spu = spu_hit["_source"]sku = spu_sku_map.get(spu["spu_id"], {})merged_result.append({"spu": spu,"lowest_price_sku": sku})

4. 預連接數據(Denormalization)(推薦)

場景:讀多寫少,需快速查詢(如商品列表頁)。
示例:將常用 SKU 信息冗余到 SPU 文檔中。

數據結構

PUT /products/_doc/SPU001
{"spu_id": "SPU001","name": "蘋果 iPhone 14","brand": "Apple","category": "手機","min_price": 5999.00,  // 預計算:最低價格"max_price": 6799.00,  // 預計算:最高價格"default_sku": {  // 預定義:默認 SKU"sku_id": "SKU001","color": "黑色","size": "128GB","price": 5999.00},"sku_summary": [  // 預聚合:SKU 摘要{"color": "黑色", "size": "128GB", "price": 5999.00},{"color": "藍色", "size": "256GB", "price": 6799.00}]
}

查詢示例

  • 需求:查找價格區間在 5000-6500 的手機,返回 SPU 及默認 SKU。
  • 實現
{"query": {"range": {"min_price": {"gte": 5000, "lte": 6500}}},"_source": ["spu_id", "name", "brand", "default_sku"]
}

方案對比

方法查詢性能寫入性能數據一致性適用場景
嵌套對象SKU 數量少,需原子性操作
父子關系SKU 動態變化,需獨立管理
應用層關聯跨索引關聯,數據量大
預連接數據最高讀多寫少,實時性要求低

優化建議

  1. 嵌套對象深度限制:避免超過 1000 個嵌套文檔,否則性能下降。
  2. 父子關系分片一致性:父子文檔必須在同一分片(通過 routing 參數保證)。
  3. 應用層關聯批量查詢:使用 terms 查詢替代循環單條查詢。
  4. 預連接數據更新策略:通過異步任務(如消息隊列)更新冗余字段。

根據實際業務場景(如 SKU 數量、讀寫比例、實時性要求)選擇合適的方案,或組合使用多種方案。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/91889.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/91889.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/91889.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Objective-c 初階 —— Runtime(方法交換 消息傳遞)

一、消息傳遞1、什么是消息[a func1];我們會把這種用方括號來調函數的方式稱為發消息。對于這個例子&#xff0c;就相當于我們給 a 這個對象發了個 func1 的消息&#xff08;個人認為指令更好理解&#xff09;。2、什么是 selectorselector 就是一個函數區分器。它只會給這個方…

【計算機網絡架構】樹型架構簡介

引言在當今數字化時代&#xff0c;網絡架構如同復雜的神經系統&#xff0c;支撐著各種信息的流通與交互。從個人日常的網絡瀏覽、在線購物&#xff0c;到企業的遠程辦公、數據存儲&#xff0c;再到國家層面的政務信息化、智慧城市建設&#xff0c;網絡架構都扮演著不可或缺的角…

llama-factory快速開始

llama-factory快速開始 文章目錄llama-factory快速開始前言一、環境配置1.1 訓練順利運行需要包含4個必備條件1.2 llama-factory下載1.3 環境下載1.4 硬件環境校驗二、啟動前言 https://github.com/hiyouga/LLaMA-Factory/blob/main/README_zh.md這是GitHub中文介紹文檔&#…

408數據結構強化(自用)

常用代碼片段&#xff08;持續更新&#xff09;折半查找void SearchBinary(int A[];int x){int low 0, high n-1, mid;while(low<high){mid (lowhigh)/2;if(A[mid]x) break;else if(A[mid] < x) low mid 1;else high mid - 1;}順序表逆置void Reverse(SqList &…

linux cpu頻率和AVS調壓等級

1&#xff0c;linux常見的cpu頻率對應的電壓等級對應參數表如下:頻率&#xff08;GHz&#xff09;電壓&#xff08;V&#xff09;1.61.41.41.21.21.01.00.82&#xff0c;avs調壓的幾種方式linux內核宏解釋Linux內核中&#xff0c;AVS調壓的實現依賴于一些宏定義和配置選項&…

Input輸入和Screen相關

知識點using System.Collections; using System.Collections.Generic; using UnityEngine;public class Lesson11 : MonoBehaviour {// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){#region 注意&#xff0c…

如何在CSDN變現?如何賺錢?如何漲粉?如何找到優質大V博主合作伙伴?

&#x1f525; 2025最新 如何在CSDN變現&#xff1f;如何賺錢&#xff1f;如何跟對人&#xff1f;如何找到優質博主合作伙伴&#xff1f; 大家好&#xff0c;我是貓頭虎&#xff0c;今天??想和大家聊聊在CSDN平臺變現的問題。這也是絕大多數伙伴非常關心的一個話題——其實&…

OpenCV特征點提取算法orb、surf、sift對比

下面是 OpenCV 中三種常用特征點提取算法&#xff1a;ORB、SURF 和 SIFT 的詳細對比&#xff0c;從 算法原理、性能、使用限制 和 適用場景 多維度進行總結&#xff0c;幫助大家在實際項目中合理選擇。一覽表&#xff1a;ORB vs. SURF vs. SIFT屬性/算法ORBSURFSIFT全稱Oriente…

LeafletJS 與 React:構建現代地圖應用

引言 LeafletJS 是一個輕量、靈活的 JavaScript 地圖庫&#xff0c;廣泛用于創建交互式 Web 地圖&#xff0c;而 React 作為現代前端框架&#xff0c;以其組件化、狀態管理和虛擬 DOM 特性&#xff0c;成為構建動態用戶界面的首選工具。將 LeafletJS 與 React 結合&#xff0c…

前后端數據交互,關于表單數據傳輸問題

表單提交var formData new FormData(); // 添加每個事故ID作為單獨的參數 accidentIds.forEach(id > formData.append(accidentIds, id)); formData.append(status, statusText); $.messager.confirm(確認, 確定要將事故記錄標記為 statusText 嗎&#xff1f;, function …

新書推介 | 吉林大學出版教材《汽車智能輔助駕駛系統技術》,國產仿真工具鏈GCKontrol-GCAir教學應用

近日&#xff0c;吉林大學出版了由高鎮海教授、孫天駿副教授主編的新教材《汽車智能輔助駕駛系統技術》&#xff0c;本書系統地介紹了汽車智能輔助駕駛系統的發展需求、物理架構、功能算法、技術原理以及應用場景。在教材第17章《仿真測試》&#xff0c;應用國產化GCKontrol-GC…

從 0 到 1 玩轉 XSS - haozi 靶場:環境搭建 + 全關卡漏洞解析

文章目錄前言靶場地址0X00 直接注入0X01 閉合標簽10X02 閉合標簽20X03 繞過特殊符號10X04 繞過特殊符號20X05 繞過注釋符0X06 繞過更多符號0X07 繞過更多符號20X08 繞過閉合符號0X09 繞過URL匹配0X0A 繞過URL過濾0X0B 繞過大寫轉換10X0C 繞過大寫轉換20X0D 繞過注釋0X0E 古英語…

TF卡格式化

cmd 輸入diskpart,在新打開的窗口輸入list disk&#xff0c;然后select disk [磁盤號]&#xff0c;clean&#xff0c;回車變成未分區的。再選中磁盤&#xff0c;選中之后create partition [分區名] 回車&#xff0c;list partition&#xff0c;查看分區&#xff0c;輸入active&…

Python爬蟲實戰:研究sqlparse庫相關技術

1. 引言 1.1 研究背景與意義 在當今數據驅動的時代,SQL 作為關系型數據庫的標準查詢語言,被廣泛應用于各種數據處理和分析場景。隨著數據庫應用的不斷發展,SQL 代碼的規模和復雜度也在不斷增加,這給 SQL 代碼的編寫、維護和優化帶來了挑戰。 研究表明,低效的 SQL 查詢是…

全球天氣預報5天(經緯度版)免費API接口教程

本文全面介紹由接口盒子免費API提供的全球天氣預報API&#xff0c;支持通過經緯度坐標獲取任意地區未來5天的詳細天氣預報數據。 一、接口核心功能 ?全球覆蓋?&#xff1a;支持全球任意經緯度坐標點的天氣預報?高精度預報?&#xff1a;提供每3小時為間隔的精細化預報&…

5 基于STM32單片機的絕緣檢測系統設計(STM32代碼編寫+手機APP設計+PCB設計+Proteus仿真)

系列文章目錄 文章目錄 系列文章目錄前言1 1 資料獲取與演示視頻1.1 資料介紹1.2 資料獲取1.3 演示視頻 2 系統框架3 硬件3.1 主控制器3.2 顯示屏3.3 WIFI模塊3.4 DHT11溫濕度傳感器3.5 可調電位器 4 設計PCB4.1 安裝下載立創EDA專業版4.2 畫原理圖4.3 擺放元器件&#xff0c;設…

CPP學習之list使用及模擬實現

一、list簡介及用法 1. list簡介 list是可以在常數范圍內任意位置進行插入、刪除、修改操作的有順序性的容器&#xff0c;而且支持雙向迭代&#xff0c;其底層是雙鏈表結構&#xff0c;邏輯上連續但物理空間上不連續&#xff0c;只能通過指針來進行元素訪問&#xff0c;無法使用…

Spring Boot 參數校驗:@Valid 與 @Validated

在日常開發中&#xff0c;參數校驗是保障接口健壯性與數據安全的第一道防線。Spring Boot 為我們提供了基于 JSR-303/JSR-380 的強大校驗機制&#xff0c;通過注解與 AOP 實現了靈活且高效的數據校驗方式。本篇博客將詳細介紹 Spring Boot 中 Valid、Validated 注解的使用方法&…

linux看門狗重啟定位思路總結

1&#xff0c;看門狗定位思路&#xff08;1&#xff09;是否是死鎖導致查看日志查看是否有RCU install或者deadlock相關打印&#xff0c;如果有的話可以考慮使用lockdep死鎖檢測工具&#xff08;2&#xff09;中斷風暴查看中斷&#xff0c;抓中斷打印&#xff0c;可以查看/proc…

基于單片機直流電機測速中文液晶顯示設計

摘 要 在現在工業自動化高度發展的時期&#xff0c;幾乎所有的工業設備都離不開旋轉設備&#xff0c;形形色色的電機在不同領域發揮著很重要的作用。不同場合對電機控制要求是不同的&#xff0c;但大部分都會涉及到旋轉設備的轉速測量&#xff0c;從而利用轉速來實施對旋轉設備…