【问题标题】:Elasticsearch composite group by queries across the documents跨文档查询的 Elasticsearch 复合分组
【发布时间】:2020-03-01 05:11:56
【问题描述】:

我们有一个弹性搜索文档,其维度称为城市。每个文档将只有一个城市字段值。我有一个场景,我需要根据一个或多个城市来查询这个人。

Elasticsearch 中的文档

{
  person_id: "1",
  property_value : 25000,
  city: "Bangalore"
}
{
  person_id: "2",
  property_value : 100000,
  city: "Bangalore"
}
{
  person_id: "1",
  property_value : 15000,
  city: "Delhi"
}

注意:聚合应该在property_value上进行,group by在person_id上。

例如,

  1. 如果我查询班加罗尔,它应该返回带有 person_id 1 和 2 的文档。
  2. 如果我同时查询德里和班加罗尔,它应该返回这个

    { person_id:“1”, 属性值:40000, 城市:[“班加罗尔”,“德里”] }

【问题讨论】:

    标签: java elasticsearch kibana


    【解决方案1】:

    查看您的数据,我想出了一个示例映射、请求查询和响应。

    映射:

    PUT my_index_city
    {
      "mappings": {
        "properties": {
          "person_id":{
            "type": "keyword"
          },
          "city":{
            "type":"text",
            "fields":{
              "keyword":{       
                "type": "keyword"
              }
            }
          },
          "property_value":{
            "type": "long"
          }
        }
      }
    }
    

    样品请求:

    请注意,我使用简单的query string 来过滤具有班加罗尔和德里的文档。

    对于聚合,我在person_id 上使用了Terms Aggregation,在property_value 字段上使用了Sum Aggregation

    POST my_index_city/_search
    {
      "size": 0, 
      "query": {
        "query_string": {
          "default_field": "city",
          "query": "Bangalore Delhi"
        }
      },
      "aggs": {
        "my_person": {
          "terms": {
            "field": "person_id",
            "size": 10,
            "min_doc_count": 2
          },
          "aggs": {
            "sum_property_value": {
              "sum": {
                "field": "property_value"
              }
            }
          }
        }
      }
    }
    

    示例响应:

    {
      "took" : 3,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 3,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "aggregations" : {
        "my_person" : {
          "doc_count_error_upper_bound" : 0,
          "sum_other_doc_count" : 0,
          "buckets" : [
            {
              "key" : "1",
              "doc_count" : 2,
              "sum_property_value" : {
                "value" : 40000.0
              }
            }
          ]
        }
      }
    }
    

    注意:只有当person_id 有多个文档每个文档都有独特/不同的城市价值。

    我的意思是,如果person_id 有多个同一个城市的文档,聚合不会给出正确的答案。

    更新答案:

    除非您修改映射,否则没有直接的方法可以实现您正在寻找的内容。我所做的是,利用nested 数据类型并将person_id 的所有文档作为单个文档摄取。

    映射:

    PUT my_sample_city_index
    {
      "mappings": {
        "properties": {
          "person_id":{
            "type": "keyword"
          },
          "property_details":{
            "type":"nested",               <------ Note this
            "properties": {
              "city":{
                "type": "text",
                "fields":{
                  "keyword":{
                    "type":"keyword"
                  }
                }
              },
              "property_value":{
                "type": "long"
              }
            }
          }
        }
      }
    }
    

    示例文件:

    POST my_sample_city_index/_doc/1
    {
      "person_id": "1",
      "property_details":[
        {
          "property_value" : 25000,
          "city": "Bangalore"
        },
        {
          "property_value" : 15000,
          "city": "Delhi"
        }
        ]
    }
    
    POST my_sample_city_index/_doc/2
    {
      "person_id": "2",
      "property_details":[
        {
          "property_value" : 100000,
          "city": "Bangalore"
        }
        ]
    }
    

    聚合查询:

    POST my_sample_city_index/_search
    {
      "size": 0,
      "query": {
        "nested": {
          "path": "property_details",
          "query": {
            "query_string": {
              "default_field": "property_details.city",
              "query": "bangalore delhi"
            }
          }
        }
      },
      "aggs": {
        "persons": {
          "terms": {
            "field": "person_id",
            "size": 10
          },
          "aggs": {
            "property_sum": {
              "nested": {                          <------ Note this
                "path": "property_details"
              },
              "aggs": {
                "total_sum": {
                  "sum": {
                    "field": "property_details.property_value"
                  }
                }
              }
            }
          }
        }
      }
    }
    

    请注意,我最初在person_id 帖子上应用了一个术语查询,我已经应用了Nested Aggregation,进一步应用了metric sum aggregation 查询。

    如果一个人在同一个城市拥有多个房产,这也应该可以正常工作。

    回应:

    {
      "took" : 31,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 2,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "aggregations" : {
        "persons" : {
          "doc_count_error_upper_bound" : 0,
          "sum_other_doc_count" : 0,
          "buckets" : [
            {
              "key" : "1",
              "doc_count" : 1,
              "property_sum" : {
                "doc_count" : 2,
                "total_sum" : {
                  "value" : 40000.0
                }
              }
            },
            {
              "key" : "2",
              "doc_count" : 1,
              "property_sum" : {
                "doc_count" : 1,
                "total_sum" : {
                  "value" : 100000.0
                }
              }
            }
          ]
        }
      }
    }
    

    如果这有帮助,请告诉我!

    【讨论】:

    • 在我的情况下,它将在同一个城市拥有多个文档。而且我也尝试过你的方法,但它并没有给我同样的结果。它让我都回来了
    • 我的用例与此类似。我们可以在弹性搜索中做同样的事情吗? stackoverflow.com/questions/4763143/…
    • 您是否可以灵活地更改映射和重新索引?
    • 是的,我可以做这些操作。
    • @GarvitKhamesra 我在Updated Answer 部分发布了更新的答案。请测试并告诉我是否有帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多