使用Elasticsearch查询字段的所有唯一值

时间:2013-01-22 19:16:19

标签: search elasticsearch

如何使用 Elasticsearch 搜索给定字段的所有唯一值?

我有select full_name from authors这样的查询,所以我可以在表单上向用户显示列表。

5 个答案:

答案 0 :(得分:18)

您可以在'full_name'字段中设置terms facet。但是为了正确地执行此操作,您需要确保在索引时不对其进行标记,否则构面中的每个条目都将是字段内容的一部分。您很可能需要在映射中将其配置为“not_analyzed”。如果您还在搜索它并且仍想要对其进行标记,则可以使用multi field以两种不同的方式对其进行索引。

您还需要考虑到,取决于属于full_name字段的唯一术语的数量,此操作可能很昂贵并且需要相当多的内存。

答案 1 :(得分:12)

对于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

答案 2 :(得分:4)

现有答案在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类似,但提供实时光标而不是保留搜索上下文。因此,它对于实时请求更有效。

答案 3 :(得分:2)

<强>直觉: 用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
}

答案 4 :(得分:1)

为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个文档,我们不需要这些文档。

参考:bucket terms aggregation

另请注意,根据this page,facet已被Elasticsearch 1.0中的聚合所取代,它们是facet的超集。