聚合可以在elasticsearch中有两个键

时间:2016-12-21 18:58:46

标签: elasticsearch aggregation nest

假设我有一个带有嵌套文档的索引,如下所示:

{
  "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”文档的计数聚合,这些文档返回roomType与categoryCode匹配搜索查询的categoryCode和categoryCode。我是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
));

1 个答案:

答案 0 :(得分:1)

您确实可以使用ElasticSearch执行此操作,但它不像SQL中那样干净。我们可以使用Nested Aggregations完成此操作。

设置

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

categoryCode | selectorCode |计数

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

  3. 聚合(SQL中的组)
  4. 在“selectorCode”上创建了“嵌套”或“子”聚合

  5. 结果

    {
      "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显示s2显示s1doc_count显示for (var prop in data) { if (data.hasOwnProperty(prop)) { // Logic here } } 分别为{1}}的显示内容。

    希望这有帮助,我会让你把所有这些都变成一个NEST查询。