使用Elasticsearch查询字段的所有唯一值
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Elasticsearch查询字段的所有唯一值相关的知识,希望对你有一定的参考价值。
如何使用Elasticsearch搜索给定字段的所有唯一值?
我有像select full_name from authors
这样的查询,所以我可以在表单上向用户显示列表。
你可以在'full_name'字段上创建一个terms facet。但是为了正确地执行此操作,您需要确保在索引时不对其进行标记,否则构面中的每个条目都将是字段内容的一部分。您很可能需要在映射中将其配置为“not_analyzed”。如果你也在搜索它并且你仍然想要标记它,你可以使用multi field以两种不同的方式对其进行索引。
您还需要考虑到,取决于作为full_name字段一部分的唯一术语的数量,此操作可能很昂贵并且需要相当多的内存。
对于Elasticsearch 1.0及更高版本,您可以利用terms aggregation
执行此操作,
查询DSL:
{
"aggs": {
"NAME": {
"terms": {
"field": "",
"size": 10
}
}
}
}
一个真实的例子:
{
"aggs": {
"full_name": {
"terms": {
"field": "authors",
"size": 0
}
}
}
}
然后你可以获得authors
字段的所有唯一值。 size = 0表示不限制术语数(这要求es为1.1.0或更高版本)。
响应:
{
...
"aggregations" : {
"full_name" : {
"buckets" : [
{
"key" : "Ken",
"doc_count" : 10
},
{
"key" : "Jim Gray",
"doc_count" : 10
},
]
}
}
}
见Elasticsearch terms aggregations。
由于以下原因,现有答案在Elasticsearch 5.X中对我不起作用:
- 索引时我需要对输入进行标记。
"size": 0
无法解析因为“[size]必须大于0”。- "Fielddata is disabled on text fields by default."这意味着默认情况下您无法搜索
full_name
字段。但是,未分析的keyword
字段可用于聚合。
解决方案1:使用Scroll API。它的工作原理是保留搜索上下文并发出多个请求,每次返回后续批次的结果。如果您使用的是Python,则elasticsearch模块具有scan()
helper function来处理滚动并返回所有结果。
解决方案2:使用Search After API。它与Scroll类似,但提供实时光标而不是保留搜索上下文。因此,它对于实时请求更有效。
直觉:用SQL术语:
Select distinct full_name from authors;
相当于
Select full_name from authors group by full_name;
因此,我们可以使用ElasticSearch中的分组/聚合语法来查找不同的条目。
假设以下是弹性搜索中存储的结构:
[{
"author": "Brian Kernighan"
},
{
"author": "Charles Dickens"
}]
什么不起作用:简单聚合
{
"aggs": {
"full_name": {
"terms": {
"field": "author"
}
}
}
}
我收到以下错误:
{
"error": {
"root_cause": [
{
"reason": "Fielddata is disabled on text fields by default...",
"type": "illegal_argument_exception"
}
]
}
}
什么像魅力一样:在字段中追加.keyword
{
"aggs": {
"full_name": {
"terms": {
"field": "author.keyword"
}
}
}
}
样本输出可以是:
{
"aggregations": {
"full_name": {
"buckets": [
{
"doc_count": 372,
"key": "Charles Dickens"
},
{
"doc_count": 283,
"key": "Brian Kernighan"
}
],
"doc_count": 1000
}
}
}
奖金提示:
让我们假设有问题的字段嵌套如下:
[{
"authors": [{
"details": [{
"name": "Brian Kernighan"
}]
}]
},
{
"authors": [{
"details": [{
"name": "Charles Dickens"
}]
}]
}
]
现在正确的查询变为:
{
"aggregations": {
"full_name": {
"aggregations": {
"author_details": {
"terms": {
"field": "authors.details.name"
}
}
},
"nested": {
"path": "authors.details"
}
}
},
"size": 0
}
为Elasticsearch 5.2.2工作
curl -XGET http://localhost:9200/articles/_search?pretty -d '
{
"aggs" : {
"whatever" : {
"terms" : { "field" : "yourfield", "size":10000 }
}
},
"size" : 0
}'
"size":10000
意味着获得(最多)10000个唯一值。如果没有这个,如果您有超过10个唯一值,则只返回10个值。
"size":0
意味着结果,"hits"
将不包含任何文件。默认情况下,返回10个文档,这是我们不需要的。
另请注意,根据this page,faceme已被Elasticsearch 1.0中的聚合所取代,它们是facets的超集。
以上是关于使用Elasticsearch查询字段的所有唯一值的主要内容,如果未能解决你的问题,请参考以下文章
[Elasticsearch] 关于字段重复值的常用查询和操作总结
Elasticsearch 分组聚合查询(bucket) --- 2022-04-03
如何在elasticsearch中为给定查询按字段获取不同的结果?