【问题标题】:Can an aggregation have two keys in elasticsearch聚合可以在弹性搜索中有两个键吗
【发布时间】:2017-05-07 07:20:58
【问题描述】:

假设我有一个包含如下嵌套文档的索引:

{
  "mappings": {
    "assignment": {
      "properties":{
        "id": {
        "type": "string"
      },
      "location": {
        "type": "string"
      },
      "typeOfLoss":{
        "type": "string"
      },
      "lineItems": {
        "type": "nested",
        "properties": {
          "categoryCode":{
            "type": "string"
          },
          "selectorCode":{
            "type": "string"
          },
          "roomType": {
            "type": "string"
          }
        }
}

我现在想要获取“lineItems”文档的计数聚合,这些文档返回房间类型与搜索查询匹配的选择器代码和类别代码。我是 elasticsearch 新手,可以用 SQL 编写查询

SELECT COUNT(*) as theCount, ln.category_code, ln.selector_code
FROM line_items as ln, assignment
WHERE assignment.location = "84043"
AND assignment.typeOfLoss = "Fire"
AND ln.roomType = "kitchen"
GROUP BY ln.category_code, ln.selector_code
ORDER BY theCount DESC;

我已经开始进行 NEST 查询,但遇到了一些问题,希望有人能指出正确的方向。

var typeOfLossQuery = new TermQuery
{
  Field = "typeOfLoss",
  Value = typeOfLoss
};

var locationQuery = new TermQuery
{
  Field = "location",
  Value = location
};

var roomTypeQuery = new TermQuery
{
  Field = "roomType",
  Value = roomType
};

var result = client.Search<LineItem>(s => s
  .From(0)
  .Size(numberOfItems)
  .Query(q => q.HasParent<Assignment>(a => a
    .Query(x =>x
      .MatchAll() && typeOfLossQuery && locationQuery
    )
  ) && q.MatchAll() && roomTypeQuery
));

【问题讨论】:

    标签: elasticsearch aggregation nest


    【解决方案1】:

    您确实可以使用 ElasticSearch 做到这一点,但它不像 SQL 那样干净。我们可以通过Nested Aggregations 来实现这一点。

    设置

    我将设置数据,以便您在 SQL 中获得以下等效结果:

    分类代码 |选择器代码 |数

    c1 | s1 | 1

    c1 | s2 | 2

    PUT test1
    
    PUT test1/_mapping/type1
    {
      "properties": {
        "id": {
          "type": "string"
        },
        "location": {
          "type": "string"
        },
        "typeOfLoss": {
          "type": "string"
        },
        "lineItems": {
          "type": "nested",
          "properties": {
            "categoryCode": {
              "type": "string",
              "fielddata": true
            },
            "selectorCode": {
              "type": "string",
              "fielddata": true
            },
            "roomType": {
              "type": "string"
            }
          }
        }
      }
    }
    
    POST test1/type1
    {
      "location":"l1",
      "lineItems":
        {
          "categoryCode": "c1",
          "selectorCode": "s1",
          "roomType": "r1"
        }
    }
    
    POST test1/type1
    {
      "location":"l1",
      "lineItems":
        {
          "categoryCode": "c1",
          "selectorCode": "s2",
          "roomType": "r1"
        }
    }
    
    POST test1/type1
    {
      "location":"l1",
      "lineItems":
        {
          "categoryCode": "c1",
          "selectorCode": "s2",
          "roomType": "r1"
        }
    }
    

    查询

    GET test1/type1/_search
    {
      "size": 0,
      "query": {
        "nested": {
          "path": "lineItems",
          "query": {
            "term": {
              "lineItems.roomType": {
                "value": "r1"
              }
            }
          }
        }
      },
      "aggs": {
        "nestedAgg": {
          "nested": {
            "path": "lineItems"
          },
          "aggs": {
            "byCategory": {
              "terms": {
                "field": "lineItems.categoryCode",
                "size": 10
              },
              "aggs": {
                "bySelector": {
                  "terms": {
                    "field": "lineItems.selectorCode",
                    "size": 10
                  }
                }
              }
            }
          }
        }
      }
    }
    

    我的查询是这样说的:

    1. 只显示数据where roomType = 'r1'

    2. categoryCode聚合(SQL 中的组)

    3. 在“selectorCode”上创建了“嵌套”或“子”聚合

    结果

    {
      "took": 6,
      "timed_out": false,
      "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
      },
      "hits": {
        "total": 3,
        "max_score": 0,
        "hits": []
      },
      "aggregations": {
        "nestedAgg": {
          "doc_count": 3,
          "byCategory": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
              {
                "key": "c1",
                "doc_count": 3,
                "bySelector": {
                  "doc_count_error_upper_bound": 0,
                  "sum_other_doc_count": 0,
                  "buckets": [
                    {
                      "key": "s2",
                      "doc_count": 2
                    },
                    {
                      "key": "s1",
                      "doc_count": 1
                    }
                  ]
                }
              }
            ]
          }
        }
      }
    }
    

    所以结果返回一个聚合列表。聚合内部是一个“桶”。请注意,byCategory 的外部存储桶显示 doc_count 为 3。这是因为数据库中有 3 条记录匹配。

    然后,嵌套在其中的是 bySelector 存储桶,显示 s2s1doc_count 分别为 2 和 1。

    希望对您有所帮助,我会让您将所有这些变成 NEST 查询。

    【讨论】:

    • 感谢所有的努力!我认为这回答了我的问题,即你不能有两个键,但不能解决我的问题。如果我有两个 CategoryCodes:C1 和 C2,在 C1 内部我有 SelectorCode:S1、S1、S2 和 S3,那么在 C2 中我有 SelectorCodes:S1、S1、S1。我想将 C2, S1 作为第一项,因为这对 CategoryCode 和 SelectorCode 发生得最多,但在您的示例中,我将获得 C1, S1 然后是 C1,S2 然后是 C1,S3 因为我们按 CategoryCode 然后按 SelectorCode 分组.
    • 我听到你在说什么。所有的数据都在那里,但是您需要做一些工作才能按照您的意愿安排它。你不能只是ORDER BY COUNT(1) DESC
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-22
    • 2017-03-10
    • 1970-01-01
    • 2019-11-08
    • 2021-02-19
    • 2023-03-18
    • 2021-10-11
    相关资源
    最近更新 更多