弹性搜索中的复杂查询
Complex query in elasticsearch
我有一个包含折扣价格的文档结构。仅当满足该折扣的所有条件时才应用折扣。
我努力找出一个查询来解决我在下面提到的用例,但我想我最终将不得不使用脚本功能。有没有一种方法可以在不编写脚本的情况下为以下用例构建查询?
{
"name": "Brown Teddy With Hat",
"prices": {
"basePrice": {
"price": 3000, // actual price
"discounts": [
{ "price": -10, "conditions": ["value1"] },
{ "price": -20, "conditions": ["value5", "value7"] }, // two conditions
{ "price": -30, "conditions": ["value6"] },
{ "price": -40, "conditions": [] } // no conditions
]
},
"installmentPrice": {...} // ignore for now
}
}
我想对所有符合条件的折扣进行汇总。将有一个包含一些条件值的输入数组,例如 [value5, value6, value1]。折扣条件应该是输入数组的一个子集。
在上面的示例中:将应用折扣 -10、-30 和 -40。我想用实际价格(3000)减去折扣,然后按折扣后的价格排序。
我尝试了 terms_set
查询,但它适用于简单的情况,例如带有数组字段的文档并将输入与该数组匹配,但对于我的情况,折扣是多重的和嵌套的 terms_set
无法正常工作。
Elasticsearch 版本 - 6.6.1
没有帮助的参考资料:
https://discuss.elastic.co/t/subsets/46488
https://discuss.elastic.co/t/match-all-terms-in-document-array/24793
我花了一些时间终于可以使用terms_set了。
我还在折扣中添加了一个 requiredMatch 字段。
对我来说,requiredMatch 字段的值等于条件数组的长度。我们也可以不加这个字段,使用脚本来获取条件数组的长度。
条件数组为空的情况不起作用。我将通过始终向条件数组和输入数组添加一个 "default" 值来破解它。因此空条件将始终按预期匹配。
这是解决我的用例的查询:
{
"aggs": {
"sorted_by_price": {
"aggs": {
"nested_discounts_aggs": {
"nested": {
"path": "prices.basePrice.discounts"
},
"aggs": {
"conditions_set_match": {
"filter": {
"terms_set": {
"prices.basePrice.discounts.conditions": {
"terms": [
"facebook",
"agreement12",
"bestxl",
"useless",
"magenta"
],
"minimum_should_match_field": "prices.basePrice.discounts.requiredMatch"
}
}
},
"aggs": {
"finalPrice": {
"sum": {
"field": "prices.basePrice.discounts.price"
}
}
}
}
}
}
},
"terms": {
"field": "_id",
"order": {
"nested_discounts_aggs>conditions_set_match>finalPrice": "desc"
},
"size": 5
}
}
}
}
新文档如下所示:
{
"name": "Brown Teddy With Hat",
"prices": {
"basePrice": {
"discounts": [
{ "price": 3000, "conditions": ["default"], "requiredMatch": 1 }, // actual price
{ "price": -10, "conditions": ["value1"], "requiredMatch": 1 },
{ "price": -20, "conditions": ["value5", "value7"], "requiredMatch": 2 }, // two conditions
{ "price": -30, "conditions": ["value6"], "requiredMatch": 1 },
{ "price": -40, "conditions": ["default"], "requiredMatch": 1 } // no conditions
]
},
"installmentPrice": {...} // ignore for now
}
}
剩下的唯一部分就是在折扣的基础上加价。我将通过删除价格字段并将实际价格作为具有正值的折扣来实现。请注意折扣有负值。
我有一个包含折扣价格的文档结构。仅当满足该折扣的所有条件时才应用折扣。
我努力找出一个查询来解决我在下面提到的用例,但我想我最终将不得不使用脚本功能。有没有一种方法可以在不编写脚本的情况下为以下用例构建查询?
{
"name": "Brown Teddy With Hat",
"prices": {
"basePrice": {
"price": 3000, // actual price
"discounts": [
{ "price": -10, "conditions": ["value1"] },
{ "price": -20, "conditions": ["value5", "value7"] }, // two conditions
{ "price": -30, "conditions": ["value6"] },
{ "price": -40, "conditions": [] } // no conditions
]
},
"installmentPrice": {...} // ignore for now
}
}
我想对所有符合条件的折扣进行汇总。将有一个包含一些条件值的输入数组,例如 [value5, value6, value1]。折扣条件应该是输入数组的一个子集。
在上面的示例中:将应用折扣 -10、-30 和 -40。我想用实际价格(3000)减去折扣,然后按折扣后的价格排序。
我尝试了 terms_set
查询,但它适用于简单的情况,例如带有数组字段的文档并将输入与该数组匹配,但对于我的情况,折扣是多重的和嵌套的 terms_set
无法正常工作。
Elasticsearch 版本 - 6.6.1
没有帮助的参考资料:
https://discuss.elastic.co/t/subsets/46488
https://discuss.elastic.co/t/match-all-terms-in-document-array/24793
我花了一些时间终于可以使用terms_set了。
我还在折扣中添加了一个 requiredMatch 字段。
对我来说,requiredMatch 字段的值等于条件数组的长度。我们也可以不加这个字段,使用脚本来获取条件数组的长度。
条件数组为空的情况不起作用。我将通过始终向条件数组和输入数组添加一个 "default" 值来破解它。因此空条件将始终按预期匹配。
这是解决我的用例的查询:
{
"aggs": {
"sorted_by_price": {
"aggs": {
"nested_discounts_aggs": {
"nested": {
"path": "prices.basePrice.discounts"
},
"aggs": {
"conditions_set_match": {
"filter": {
"terms_set": {
"prices.basePrice.discounts.conditions": {
"terms": [
"facebook",
"agreement12",
"bestxl",
"useless",
"magenta"
],
"minimum_should_match_field": "prices.basePrice.discounts.requiredMatch"
}
}
},
"aggs": {
"finalPrice": {
"sum": {
"field": "prices.basePrice.discounts.price"
}
}
}
}
}
}
},
"terms": {
"field": "_id",
"order": {
"nested_discounts_aggs>conditions_set_match>finalPrice": "desc"
},
"size": 5
}
}
}
}
新文档如下所示:
{
"name": "Brown Teddy With Hat",
"prices": {
"basePrice": {
"discounts": [
{ "price": 3000, "conditions": ["default"], "requiredMatch": 1 }, // actual price
{ "price": -10, "conditions": ["value1"], "requiredMatch": 1 },
{ "price": -20, "conditions": ["value5", "value7"], "requiredMatch": 2 }, // two conditions
{ "price": -30, "conditions": ["value6"], "requiredMatch": 1 },
{ "price": -40, "conditions": ["default"], "requiredMatch": 1 } // no conditions
]
},
"installmentPrice": {...} // ignore for now
}
}
剩下的唯一部分就是在折扣的基础上加价。我将通过删除价格字段并将实际价格作为具有正值的折扣来实现。请注意折扣有负值。