Elasticsearch嵌套聚合桶中bucket_selector不生效问题咨询
问题原因
你当前的写法报错核心原因是bucket_selector的层级和引用的聚合路径不符合要求:
你把filtered_product_quantity和unique_product平级放置,而unique_product是terms聚合,返回的是多桶数组,你通过unique_product.key和unique_product>quantity拿到的是数组对象,不是bucket_selector要求的单值数值,因此触发报错。
同时你原脚本存在类型不匹配隐患:product.id是数值类型,而你参数requiredQuantities的key是字符串类型,直接取值会拿不到对应配置。
正确实现方案
根据你的需求,分两种常见场景提供写法:
场景1:过滤每个product.id对应的子桶,仅保留满足数量要求的product记录
把bucket_selector放到unique_product的子聚合层级,此时每个桶对应单个product.id,能拿到单值的key和sum结果:
GET _search { "size": 0, "query": { "bool": { "must": [ { "terms": { "product.id": [20,21,22,23,24] } } ] } }, "aggs": { "carts": { "terms": { "field": "item.cart_key" }, "aggs": { "unique_product": { "terms": { "field": "product.id" }, "aggs": { "quantity": { "sum": { "field": "item.quantity" } }, "filtered_product": { "bucket_selector": { "buckets_path": { "productId": "_key", "productQuantity": "quantity" }, "script": { "params": { "requiredQuantities": { "20": null, "21": null, "22": null, "23": 3, "24": null } }, "lang": "painless", "source": """ def minQty = params.requiredQuantities[params.productId.toString()]; // 没有设置最小数量的product直接保留,设置了的需要满足数量要求 return minQty == null || params.productQuantity >= minQty; """ } } } } } } } } }
场景2:过滤整个cart_key桶,仅保留所有指定product都满足数量要求的购物车
如果你需要的是只留下完全满足所有数量要求的购物车,那需要先对每个指定的product.id单独做sum聚合,再统一判断:
GET _search { "size": 0, "query": { "bool": { "must": [ { "terms": { "product.id": [20,21,22,23,24] } } ] } }, "aggs": { "carts": { "terms": { "field": "item.cart_key" }, "aggs": { "sum_p20": { "filter": {"term": {"product.id": 20}}, "aggs": {"qty": {"sum": {"field": "item.quantity"}}} }, "sum_p21": { "filter": {"term": {"product.id": 21}}, "aggs": {"qty": {"sum": {"field": "item.quantity"}}} }, "sum_p22": { "filter": {"term": {"product.id": 22}}, "aggs": {"qty": {"sum": {"field": "item.quantity"}}} }, "sum_p23": { "filter": {"term": {"product.id": 23}}, "aggs": {"qty": {"sum": {"field": "item.quantity"}}} }, "sum_p24": { "filter": {"term": {"product.id": 24}}, "aggs": {"qty": {"sum": {"field": "item.quantity"}}} }, "filter_cart": { "bucket_selector": { "buckets_path": { "p20": "sum_p20>qty", "p21": "sum_p21>qty", "p22": "sum_p22>qty", "p23": "sum_p23>qty", "p24": "sum_p24>qty" }, "script": { "params": { "requiredQuantities": { "20": null, "21": null, "22": null, "23": 3, "24": null } }, "source": """ def check(id, qty) { def min = params.requiredQuantities[id]; return min == null || qty >= min; } return check("20", params.p20) && check("21", params.p21) && check("22", params.p22) && check("23", params.p23) && check("24", params.p24); """ } } } } } } }
内容的提问来源于stack exchange,提问作者Toto NaBendo
相关产品推荐
相关产品推荐

