【问题标题】:How to get latest values for each group with an Elasticsearch query?如何使用 Elasticsearch 查询获取每个组的最新值?
【发布时间】:2015-05-14 23:49:50
【问题描述】:

我在 Elasticsearch 上索引了一些文档,看起来像这些示例:

{'country': 'France', 'collected': '2015-03-12', 'value': 20}
{'country': 'Canada', 'collected': '2015-03-12', 'value': 21}
{'country': 'Brazil', 'collected': '2015-03-12', 'value': 33}
{'country': 'France', 'collected': '2015-02-01', 'value': 10}
{'country': 'Canada', 'collected': '2015-02-01', 'value': 11}
{'country': 'Mexico', 'collected': '2015-02-01', 'value': 9}
...

我想构建一个查询,每个国家/地区获取一个结果,只获取带有max(collected) 的结果。

因此,对于上面显示的示例,结果将类似于:

{'country': 'France', 'collected': '2015-03-12', 'value': 20}
{'country': 'Canada', 'collected': '2015-03-12', 'value': 21}
{'country': 'Brazil', 'collected': '2015-03-12', 'value': 33}
{'country': 'Mexico', 'collected': '2015-02-01', 'value': 9}

我意识到我需要在 country 上进行聚合,但我不明白如何限制 max(collected) 上的结果。

有什么想法吗?

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    您可以使用在 country 字段上分组的 top_hits 聚合,每组返回 1 个文档,并按收集的日期降序排列文档:

    POST /test/_search?search_type=count
    {
        "aggs": {
            "group": {
                "terms": {
                    "field": "country"
                },
                "aggs": {
                    "group_docs": {
                        "top_hits": {
                            "size": 1,
                            "sort": [
                                {
                                    "collected": {
                                        "order": "desc"
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        }
    }
    

    【讨论】:

    • 您是否没有收到类似以下的错误:“默认情况下,文本字段上的字段数据已禁用。在 [country] 上设置 fielddata=true 以便通过反转倒排索引将字段数据加载到内存中。请注意,此但是可以使用大量内存。或者使用关键字字段。?如果是,您是如何解决的?
    • 嗨,由于某种原因,我们得到了一个例外:“原因”:“没有 [count] 的搜索类型”你能帮我吗?
    • 您好,此选项今天已过时,如下所示:discuss.elastic.co/t/no-search-type-for-count/101994/2
    • 你好,如果我想说如果任何国家的最后一个结果是今天的,我想排除整个国家怎么办?
    • 2020 在这里。工作得很好,版本 7.4。我添加了一个答案,展示了如何添加额外的过滤器。
    【解决方案2】:

    对于像user1892775 这样遇到“默认情况下在文本字段上禁用字段数据...”的用户,您可以创建一个多字段 (https://www.elastic.co/guide/en/elasticsearch/reference/current/multi-fields.html)。所以你可能有这样的映射:

    "mapping": {
        "properties": {
          "country": {"type": "string", "fields": {"raw": {"type": "string", "index": "not_analyzed"}}}
    }
    

    那么你的查询看起来像

    POST /test/_search?search_type=count
    {
        "aggs": {
        "group": {
            "terms": {
                "field": "country.raw"
            },
            "aggs": {
                "group_docs": {
                    "top_hits": {
                        "size": 1,
                        "sort": [
                            {
                                "collected": {
                                    "order": "desc"
                                }
                            }
                        ]
                    }
                }
            }
        }
      }
    }
    

    (注意使用国家/地区。原始

    【讨论】:

      【解决方案3】:

      标记为正确的答案对我很有帮助。 这是我添加一些额外过滤器的方法。这是 AWS 上的 7.4 版。

      我分组的字段是一个名为 tags 的关键字字段。

      • 对于每个组(标签),获取按 date_uploaded 降序排序的前 3 个文档。

      • 还显示每个组(标签)内的文档总数。

      • 仅考虑属于用户 22 的未删除文档。

      • 仅返回 10 个组(标签),按字母顺序排序。

      • 对于每个文档,返回其 ID (book_id) 和 date_uploaded。 (默认是返回所有信息。)

      • Size:0 使查询不会返回有关所有文档的大量信息。

          {'query': {'bool': {'filter': [{'terms': {'user_id': [22]}}, {'terms': {'deleted': ['false']}}]}},
           'size': 0,
           "aggs": {
              "group": {
                  "terms": {
                      "field": "tags.keyword",
                      "size":10,
                      "order":{ "_key": "asc" }
                  },  
                  "aggs": {
                      "group_docs": {
                          "top_hits": {
                              "size": 3,
                              "_source":["book_id","date_uploaded"],
                              "sort": [ {"date_uploaded": { "order": "desc" }}]
                          }
                      }
                  }
              }
          }
        

        }

      这里是如何获取每个组(在我的例子中是标签)以及每个组的文档匹配。

      query_results = ... result of query
      buckets = query_results["aggregations"]["group"]["buckets"]
      for bucket in buckets:
          tag = bucket["key"]
          tag_doc_count = bucket["doc_count"]
          print tag, tag_total_doc_count
          tag_hits = bucket["group_docs"]["hits"]["hits"]
          for hit in tag_hits:
              source = hit["_source"]
              print source["book_id"], source["date_uploaded"]
      

      仅供参考,“组”一词可以命名为任何名称。从查询结果中获取存储桶时,请确保使用相同的名称。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-02-02
        • 1970-01-01
        • 1970-01-01
        • 2015-05-12
        • 1970-01-01
        • 2021-01-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多