【问题标题】:Elasticsearch filter document group by fieldElasticsearch 按字段分组过滤文档
【发布时间】:2014-11-17 03:42:32
【问题描述】:

我有一些文件:

{"name": "John", "district": 1},
{"name": "Mary", "district": 2},
{"name": "Nick", "district": 1},
{"name": "Bob", "district": 3},
{"name": "Kenny", "district": 1}

如何按地区过滤/选择不同的文档?

{"name": "John", "district": 1},
{"name": "Mary", "district": 2},
{"name": "Bob", "district": 3}

在 SQL 中,我可以使用 GROUP BY。我尝试了术语聚合,但它只返回 count distinct。

"aggs": {
  "distinct": {
    "terms": {
      "field": "district",
      "size": 0
    }
  }
}

感谢您的帮助! :-)

【问题讨论】:

  • 我的回答能解决你的问题吗

标签: elasticsearch group-by distinct


【解决方案1】:

Elastic 搜索不提供关于 value 或 group by unique value 的不同文档。 但是如果您使用 java 客户端或者可以将其转换为您合适的语言,则可以解决此问题

SearchResponse response = client.prepareSearch().execute().actionGet();
SearchHits hits = response.getHits();

Iterator<SearchHit> iterator = hits.iterator();
Map<String, SearchHit> distinctObjects = new HashMap<String,SearchHit>();
while (iterator.hasNext()) {
    SearchHit searchHit = (SearchHit) iterator.next();
    Map<String, Object> source = searchHit.getSource();
    if(source.get("district") != null){
        distinctObjects.put(source.get("district").toString(),source);
    }

} 

【讨论】:

  • 如果您使用分页怎么办?如果您每页获得 10 个结果,是否获得包含 8 个结果的页面,其他 10 个和其他 7 个结果?
  • 这不是解决方法。它是自己的轮子重写。你要读取你记忆中的所有对象吗?如果有数百万个呢?
【解决方案2】:

如果您的 ElasticSearch 版本是 1.3 或更高版本,您可以使用类型为 top_hits 的子聚合,它会(默认情况下)为您提供按查询分数排序的前三个匹配文档(此处为 1,因为您使用 match_all 查询)。

您可以将size参数设置为3以上。

以下数据集和查询:

POST /test/districts/
{"name": "John", "district": 1}

POST /test/districts/
{"name": "Mary", "district": 2}

POST /test/districts/
{"name": "Nick", "district": 1}

POST /test/districts/
{"name": "Bob", "district": 3}

POST test/districts/_search
{
  "size": 0, 
  "aggs":{
    "by_district":{
      "terms": {
        "field": "district",
        "size": 0
      },
      "aggs": {
        "tops": {
          "top_hits": {
            "size": 10
          }
        }
      }
    }
  }
}

将以您想要的方式输出文档:

{
   "took": 5,
   "timed_out": false,
   "_shards": {
      "total": 5,
      "successful": 5,
      "failed": 0
   },
   "hits": {
      "total": 4,
      "max_score": 0,
      "hits": []
   },
   "aggregations": {
      "by_district": {
         "buckets": [
            {
               "key": 1,
               "key_as_string": "1",
               "doc_count": 2,
               "tops": {
                  "hits": {
                     "total": 2,
                     "max_score": 1,
                     "hits": [
                        {
                           "_index": "test",
                           "_type": "districts",
                           "_id": "XYHu4I-JQcOfLm3iWjTiOg",
                           "_score": 1,
                           "_source": {
                              "name": "John",
                              "district": 1
                           }
                        },
                        {
                           "_index": "test",
                           "_type": "districts",
                           "_id": "5dul2XMTRC2IpV_tKRRltA",
                           "_score": 1,
                           "_source": {
                              "name": "Nick",
                              "district": 1
                           }
                        }
                     ]
                  }
               }
            },
            {
               "key": 2,
               "key_as_string": "2",
               "doc_count": 1,
               "tops": {
                  "hits": {
                     "total": 1,
                     "max_score": 1,
                     "hits": [
                        {
                           "_index": "test",
                           "_type": "districts",
                           "_id": "I-9Gd4OYSRuexhP1dCdQ-g",
                           "_score": 1,
                           "_source": {
                              "name": "Mary",
                              "district": 2
                           }
                        }
                     ]
                  }
               }
            },
            {
               "key": 3,
               "key_as_string": "3",
               "doc_count": 1,
               "tops": {
                  "hits": {
                     "total": 1,
                     "max_score": 1,
                     "hits": [
                        {
                           "_index": "test",
                           "_type": "districts",
                           "_id": "bti2y-OUT3q2mBNhhI3xeA",
                           "_score": 1,
                           "_source": {
                              "name": "Bob",
                              "district": 3
                           }
                        }
                     ]
                  }
               }
            }
         ]
      }
   }
}

【讨论】:

  • 太好了,你救了我的命!!
  • 嘿@ThomasC,知道如何过滤要像这样聚合的记录吗?我已经试了半个小时了。谢谢!
  • 嗨@lisak!您不能在 top_hits 下嵌套聚合,但是,相反的情况是可能的。尝试使用过滤器聚合并在下面嵌套一个 top_hits。或者,您可以在查询部分过滤结果
  • @ThomasC 你能回答这个stackoverflow.com/questions/46764307/…
  • 这个可行,但是如果有超过 500 个独特的地区,有没有办法可以进行分页,我在哪里输入“from”关键字,术语聚合不支持它
猜你喜欢
  • 2017-02-15
  • 2018-07-04
  • 2016-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多