ElasticSearch 6.0嵌套store文档多仓库商品最低价查询及性能优化咨询
Elasticsearch 6.0 电商多仓库价格库存查询解决方案
前置字段调整
首先将store字段的索引类型设置为nested(嵌套类型),避免普通数组扁平化存储导致的价格、库存属性不匹配问题。
同时新增2个冗余字段,用于提升查询性能:
min_available_price:float类型,存储当前商品所有有库存仓库的最低价格,文档写入/更新时同步计算写入has_available_stock:boolean类型,标记商品是否存在可用库存,文档写入/更新时同步计算写入
常见问题解答
1. 多store子对象性能问题
单商品150个store子对象完全不会引发性能问题:
- 单个store子对象大小仅几十字节,150个总大小不足10KB,远低于ES单文档100MB的默认上限
- 当前量级对文档写入、查询的性能损耗可忽略,单商品store量级超过1000个时才需要考虑拆分优化
2. 有库存最低价查询最高效方案
方案一:冗余字段查询(推荐,性能零损耗)
写入文档时直接计算最低价写入min_available_price字段,查询时直接读取该字段即可,性能和普通字段查询完全一致。
历史数据批量更新脚本示例:
POST product/_update_by_query { "query": {"match_all": {}}, "script": { "lang": "painless", "source": """ def available_stores = ctx._source.store.stream().filter(s->s.available_unit > 0).collect(Collectors.toList()); ctx._source.has_available_stock = available_stores.size() > 0; if(ctx._source.has_available_stock){ ctx._source.min_available_price = available_stores.stream().mapToDouble(s->s.default_price).min().getAsDouble(); }else{ ctx._source.min_available_price = null; } """ } }
方案二:嵌套聚合查询(无需修改写入逻辑)
如果不想调整写入流程,可直接使用嵌套聚合查询,性能可满足常规电商访问量级:
POST product/_search { "query": { // 此处替换为你的商品查询条件 "match": {"title": "Product Name"} }, "aggs": { "available_stores": { "nested": {"path": "store"}, "aggs": { "in_stock_filter": { "filter": {"range": {"store.available_unit": {"gt": 0}}}, "aggs": { "min_valid_price": {"min": {"field": "store.default_price"}} } } } } } }
查询完成后从返回结果的aggregations.available_stores.in_stock_filter.min_valid_price.value中即可获取对应商品的最低可售价格。
3. 价格区间过滤/分面聚合正确方案
冗余字段方案(推荐)
价格区间过滤直接对min_available_price字段做范围查询即可,分面聚合也直接基于该字段做range聚合,不会出现匹配到非可售价格的问题,性能最高。
嵌套查询方案
如果不使用冗余字段,价格过滤必须使用嵌套查询,确保过滤条件关联同一个仓库的库存和价格属性:
POST product/_search { "query": { "bool": { "must": [ // 其他商品查询条件 { "nested": { "path": "store", "query": { "bool": { "must": [ {"range": {"store.available_unit": {"gt": 0}}}, {"range": {"store.default_price": {"gte": 100, "lte": 200}}} ] } } } } ] } } }
分面聚合逻辑和前文的最低价嵌套聚合一致,仅统计有库存仓库的价格即可保证结果符合预期。
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

