我有一些带有促销代码的数组(来自请求):
$promocodes = ['K1H5E1F1', 'M4C8A5K6', 'A3B9A45KL'];
我在Elasticsearch中有产品数据(例如,我将提供一种产品的数据):
// First product (2 promocodes matched, take a lower price 265.5 and filter this product at this price)
"price": 199,
"promocodes" : [
{
"code" : "K1H5E1F1",
"price" : 265.5
},
{
"code" : "LKDS3534K",
"price" : 357
},
{
"code" : "A3B9A45KL",
"price" : 327.5
}
]
// Second product (1 promocode matched, take a price 700 and filter this product at this price)
"price": 800,
"promocodes" : [
{
"code" : "AJ543HJB",
"price" : 500
},
{
"code" : "M4C8A5K6",
"price" : 700
}
]
// Third product (0 promocode matched, take a base price 900 and filter this product at this price)
"price": 900,
"promocodes" : [
{
"code" : "AJ87HJ90",
"price" : 750
}
]
我需要根据促销代码按价格过滤产品数据。如果您设置价格范围并有促销代码,则需要过滤产品。如果产品具有相同的促销代码,则需要以该促销代码的价格为准,而不是主价格。如果两种促销代码与一种产品匹配,那么您需要以更低的价格。在我的示例中,同一产品针对一个产品具有2个促销代码,我需要从促销代码的2个价格中减去较低的价格,并针对该特定价格进行过滤。
此请求未根据需要过滤价格:
GET dev_products/_search
{
"query": {
"bool": {
"must": [
{
"range": {
"price": {
"gte": 100,
"lte": 350
}
}
},
{
"nested": {
"path": "promocodes",
"query": {
"terms": {
"promocodes.code": [
'K1H5E1F1',
'M4C8A5K6',
'A3B9A45KL'
]
}
}
}
}
]
}
}
}
我不知道如何正确地提出请求,请寻求帮助。
答案 0 :(得分:1)
您需要使用inner hits。
{
"query": {
"bool": {
"must": [
{
"range": {
"price": {
"gte": 100,
"lte": 350
}
}
},
{
"nested": {
"path": "promocodes",
"query": {
"terms": {
"promocodes.code": [
"K1H5E1F1",
"A3B9A45KL"
]
}
},
"inner_hits": {
"sort": {"promocodes.price": "asc"},----> sort nested document by price
"size": 1 ---> return top 1 document
}
}
}
]
}
}
}
结果:
"hits" : [
{
"_index" : "index4",
"_type" : "_doc",
"_id" : "NTBFgm0BFLPFo7KPt70j",
"_score" : 2.0,
"_source" : {
"price" : 199,
"promocodes" : [
{
"code" : "K1H5E1F1",
"price" : 265.5
},
{
"code" : "LKDS3534K",
"price" : 357
},
{
"code" : "A3B9A45KL",
"price" : 327.5
}
]
},
"inner_hits" : { -----> inner hits contains nested data
"promocodes" : {
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ -----> returns one matched field
{
"_index" : "index4",
"_type" : "_doc",
"_id" : "NTBFgm0BFLPFo7KPt70j",
"_nested" : {
"field" : "promocodes",
"offset" : 0
},
"_score" : null,
"_source" : {
"code" : "K1H5E1F1",
"price" : 265.5
},
"sort" : [
265.5
]
}
]
}
}
}
}
]
编辑: 下面的逻辑检查促销代码是否匹配,然后返回具有内部匹配中促销代码值的文档。如果促销代码不匹配,并且父价格在范围内(gte和lte值),则返回该文档。
GET dev_products/_search
{
"_source": "price",
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{
"range": {
"price": {
"gte": 100,
"lte": 350
}
}
}
],
"must_not": [
{
"nested": {
"path": "promocodes",
"query": {
"bool": {
"must": [
{
"terms": {
"promocodes.code.keyword": [
"K1H5E1F1",
"A3B9A45KL"
]
}
}
]
}
},
"inner_hits": {
"sort": {
"promocodes.price": "asc"
},
"size": 1
}
}
}
]
}
},
{
"nested": {
"path": "promocodes",
"query": {
"bool": {
"must": [
{
"terms": {
"promocodes.code.keyword": [
"K1H5E1F1",
"A3B9A45KL"
]
}
},
{
"range": {
"promocodes.price": {
"gte": 100,
"lte": 350
}
}
}
]
}
},
"inner_hits": {
"sort": {
"promocodes.price": "asc"
},
"size": 1
}
}
}
]
}
}
}
EDIT-2 查询
GET dev_products/_search
{
"_source": "price",
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{
"range": {
"price": {
"gte": 100,
"lte": 350
}
}
}
],
"must_not": [
{
"nested": {
"path": "promocodes",
"query": {
"bool": {
"must": [
{
"terms": {
"promocodes.code.keyword": [
"K1H5E1F1",
"A3B9A45KL"
]
}
}
]
}
}
}
}
]
}
},
{
"bool": {
"must": [
{
"nested": {
"path": "promocodes",
"query": {
"bool": {
"must": [
{
"terms": {
"promocodes.code.keyword": [
"K1H5E1F1",
"A3B9A45KL"
]
}
},
{
"range": {
"promocodes.price": {
"lte": 350,
"gte": 100
}
}
}
]
}
},
"inner_hits": {
"sort": {
"promocodes.price": "asc"
},
"size": 1
}
}
}
],
----> don't include document if any matched promcode has value less than given range
"must_not": [
{
"nested": {
"path": "promocodes",
"query": {
"bool": {
"must": [
{
"terms": {
"promocodes.code.keyword": [
"K1H5E1F1",
"A3B9A45KL"
]
}
},
{
"range": {
"promocodes.price": {
"lt": 100
}
}
}
]
}
}
}
}
]
}
}
]
}
}
}
答案 1 :(得分:0)
如果price
和promocodes.price
的范围等于"gte":270,"lte":271
,并且就promocodes.code
等于["promo1","promo2","promo4"]
而言,该请求将不起作用-实际上,他不应该选择该产品,因为根据最低促销代码的价格是265.5
,并且不属于该范围的范围,但是他仍然选择该产品,并且没有为{{ 1}}(出于某种原因,他选择了价格为inner_hits
的{{1}}来选择"promo2"
的{{1}}。
inner_hits