Elasticsearch:在嵌套对象中作为集合的字段上按最大值过滤

时间:2016-01-05 02:29:03

标签: elasticsearch

当我在ES中进行查询时,如果discounts.percent_value集合中存在多个折扣(元素),我希望仅查看discounts字段的最大值。在下面的示例中,我只是喜欢嵌套查询来操作文档的折扣,并让它只知道60%的折扣。

我现有的过滤器看起来像这样:

discount_filter = { 
  nested: {
    path: "discounts", query: { bool: { must: [
      { range: { "discounts.percent_value" => { lte: query_filter.discount_max } } },
      { range: { "discounts.starts_at"     => { lte: "now" } } },
      { range: { "discounts.ends_at"       => { gte: "now" } } }
    ] } },
    filter: { 
      script: { 
        script: "doc['discounts.percent_value'].values.max" 
      } 
    }
  } 
}

映射:

"mappings": {
  "product": {
    "properties": {
      "discounts": {
        "type": "nested",
        "properties": {
          "ends_at": {
            "type": "date",
            "format": "dateOptionalTime"
          },
          "percent": {
            "type": "string"
            },
          "percent_value": {
            "type": "float"
          },
          "return_policy_key": {
            "type": "string",
            "index": "not_analyzed"
          },
          "starts_at": {
            "type": "date",
            "format": "dateOptionalTime"
          }
        }
      } 
    }
  }
}

示例文档(有多个折扣):

{
  "_index": "products_test_index",
  "_type": "product",
  "_id": "6",
  "_score": 1,
  "_source": {
    "id": 6,
    "name": "Some Product",
    "permalink": "some-product-42",
    "price": 100,
    "minimum_price": 0,
    "discounts": [
      {
        "starts_at": "2016-01-03T01:37:02Z",
        "ends_at": "2016-01-07T01:37:02Z",
        "percent": "40.0",
        "percent_value": "40.0",
        "return_policy_key": "0.0"
      },
      {
        "starts_at": "2016-01-03T01:37:02Z",
        "ends_at": "2016-01-07T01:37:02Z",
        "percent": "60.0",
        "percent_value": "60.0",
        "return_policy_key": "0.0"
      }
    ]
  }
}

1 个答案:

答案 0 :(得分:1)

我接近这个的方法是只选择嵌套的有效折扣(即现在包含其开始/结束日期间隔的折扣​​),然后使用nested + max聚合的组合为了获得最大的折扣:

{
  "query": {
    "nested": {
      "path": "discounts",
      "query": {
        "bool": {
          "must": [
            {
              "range": {
                "discounts.starts_at": {
                  "lte": "now"
                }
              }
            },
            {
              "range": {
                "discounts.ends_at": {
                  "gte": "now"
                }
              }
            }
          ]
        }
      }
    }
  },
  "aggs": {
    "discounts": {
      "nested": {
        "path": "discounts"
      },
      "aggs": {
        "max_discounts": {
          "max": {
            "field": "discounts.percent_value"
          }
        }
      }
    }
  }
}