elasticsearch - Elasticsearch-按价格搜索和过滤

标签 elasticsearch

我有一些带有促销代码的数组(来自请求):

$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'
                ]
              }
            }
          }
        }
      ]
    }
  }
}

我不知道如何正确提出要求,请寻求帮助。

最佳答案

您需要使用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
            }
          }
        }
      ]
    }
  }
}

编辑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
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      ]
    }
  }
}

关于elasticsearch - Elasticsearch-按价格搜索和过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58167789/

相关文章:

elasticsearch - elasticsearch查询问题,范围查询格式错误,预期为END_OBJECT,但找到FIELD_NAME

search - 在 ElasticSearch 中找到文本的返回字段

ElasticSearch增量快照不明确

elasticsearch - Elasticsearch,Kibana分类/汇总文档

elasticsearch - elasticsearch通过子聚合doc_count排除聚合桶

elasticsearch - 在Elasticsearch中增强元组

elasticsearch - 什么时候应该转移到多节点Elasticsearch集群?

elasticsearch - logstash dns 过滤器中的 hit_cache_size 如何工作?

elasticsearch - 使用多字段条件在GET中搜索

python - 收集两列数据