【发布时间】:2020-02-24 23:39:08
【问题描述】:
我正在尝试按价格筛选产品,但我完全不知道如何进行。 希望有人能对此有所了解,并指出我正确的方向。
概念
每种产品都有多个价格。 这些价格在特定日期范围内有效。 产品在某一日期的实际价格是该日期有效的最低价格。
目标
我希望能够:
- 获取特定日期的最低和最高价格
- 按特定日期的最高/最低价格过滤产品
警告:我已简化此示例的价格限制,但我无法合并日期,因此每个日期范围只有 1 个有效日期。
示例
映射:
curl -XPUT 'http://localhost:9200/price-filter-test'
curl -XPUT 'http://localhost:9200/price-filter-test/_mapping/_doc' -H 'Content-Type: application/json' -d '{
"properties": {
"id": {"type": "integer"},
"name": {"type": "text"},
"prices": {
"type": "nested",
"properties": {
"price": {"type": "integer"},
"from": {"type": "date"},
"untill": {"type": "date"}
}
}
}
}'
测试条目:
curl -XPUT 'http://localhost:9200/price-filter-test/_doc/1' -H 'Content-Type: application/json' -d '{
"id": 1,
"name": "Product A",
"prices": [
{
"price": 10,
"from": "2020-02-01",
"untill": "2020-03-01"
},
{
"price": 8,
"from": "2020-02-20",
"untill": "2020-02-21"
},
{
"price": 12,
"from": "2020-02-22",
"untill": "2020-02-23"
}
]
}'
curl -XPUT 'http://localhost:9200/price-filter-test/_doc/2' -H 'Content-Type: application/json' -d '{
"id": 2,
"name": "Product B",
"prices": [
{
"price": 20,
"from": "2020-02-01",
"untill": "2020-03-01"
},
{
"price": 18,
"from": "2020-02-20",
"untill": "2020-02-21"
},
{
"price": 22,
"from": "2020-02-22",
"untill": "2020-02-23"
}
]
}'
在2020-02-20 条目中,以下价格有效,正确的价格以粗体显示:
- 产品A:
- 10
- 8
- 产品 B:
- 20
- 18
解决方案
最小值/最大值
我已经弄清楚如何获取适用价格的最小值和最大值。 使用聚合这是非常可行的:
curl -XGET 'http://localhost:9200/price-filter-test/_search?pretty=true' -H 'Content-Type: application/json' -d '{
"query": {"match_all": {}},
"size": 0,
"aggs": {
"product_ids": {
"terms": {"field": "id"},
"aggs": {
"nested_prices": {
"nested": {"path": "prices"},
"aggs": {
"applicable_prices": {
"filter": {
"bool": {
"must": [
{"range": {"prices.from": {"lte": "2020-02-20"}}},
{"range": {"prices.untill": {"gte": "2020-02-20"}}}
]
}
},
"aggs": {
"min_price": {
"min": {"field": "prices.price"}
}
}
}
}
}
}
},
"stats_min_prices": {
"stats_bucket": {
"buckets_path": "product_ids>nested_prices>applicable_prices>min_price"
}
}
}
}'
在这里,我首先汇总不同的 ID,以确保检查每个产品的价格,然后按适用日期过滤,然后获取每个产品的最低价格。 使用 stats_bucket 聚合,我可以得到这些最低价格的最小值和最大值。
{
// ...
"aggregations" : {
// ...
"stats_min_prices" : {
"count" : 2,
"min" : 8.0,
"max" : 18.0,
"avg" : 13.0,
"sum" : 26.0
}
}
}
在这里我们看到正确的最小值(产品 A 为 8)和最大值(产品 B 为 18)
过滤
为了过滤,我需要能够根据最低价格排除产品。
例如如果我搜索价格至少为 19 的产品,我应该找不到任何产品,因为产品 B 的最低价格是 18
curl -X GET "localhost:9200/price-filter-test/_search?pretty" -H 'Content-Type: application/json' -d '{
"query": {
"nested": {
"path": "prices",
"query": {
"bool": {
"must": [
{
"range" : {
"prices.price" : {"gte" : 19}
}
},
{"range": {"prices.from": {"lte": "2020-02-20"}}},
{"range": {"prices.untill": {"gte": "2020-02-20"}}}
]
}
}
}
}
}'
但是,此尝试仍会产生“产品 B”作为匹配项,因为此日期范围内的价格之一高于 19。但是,由于它不是该日期范围内的最低价格,因此不是“正确”价格。
我完全不知道如何做到这一点。 我考虑过使用脚本字段,但我认为我需要组合 2 个(1 个用于计算适用价格,1 个用于获得最低价格),这似乎不是一个选项。
希望你能指出正确的方向
【问题讨论】:
-
你能详细说明你想要做什么,可能会有预期的结果。您尝试使用聚合结果过滤掉产品?
-
@LeBigCat 感谢您的指点,我已经更新了任务以提供更多示例。我正在尝试按“正确价格”进行过滤,这是一个我需要在查询时确定的字段,因为它与上下文相关。聚合是我为使问题更清晰而包含的一个单独的问题
标签: elasticsearch