Elasticsearch 查询返回所有记录

Posted

技术标签:

【中文标题】Elasticsearch 查询返回所有记录【英文标题】:Elasticsearch query to return all records 【发布时间】:2012-01-12 02:41:25 【问题描述】:

我在 Elasticsearch 中有一个小型数据库,出于测试目的,我想提取所有记录。我正在尝试使用表单的 URL...

http://localhost:9200/foo/_search?pretty=true&q='matchAll':''

谁能给我你用来完成此任务的 URL 吗?

【问题讨论】:

...其中“foo”是要显示所有记录的索引的名称。 所有仅使用size查询参数的答案都不正确。无论查询中size 的值如何,ES 都会返回最大index.max_result_window docs(默认为10k)作为响应。参考scrollsearch_after 【参考方案1】:

我认为这样支持 lucene 语法:

http://localhost:9200/foo/_search?pretty=true&q=*:*

size 默认为 10,因此您可能还需要&size=BIGNUMBER 才能获得超过 10 个项目。 (其中 BIGNUMBER 等于您认为大于数据集的数字)

但是,elasticsearch 文档suggests 用于大型结果集,使用扫描搜索类型。

EG:

curl -XGET 'localhost:9200/foo/_search?search_type=scan&scroll=10m&size=50' -d '

    "query" : 
        "match_all" : 
    
'

然后按照上面的文档链接建议继续请求。

编辑:scan 在 2.1.0 中已弃用。

scan 与按_doc 排序的常规scroll 请求相比没有任何好处。 link to elastic docs(@christophe-roussy 发现)

【讨论】:

谢谢。这是我想出的最后一个返回我现在需要的东西...localhost:9200/foo/_search?size=50&pretty=true&q=*:* 补充@Steve的回答,可以在这个链接elasticsearch.org/guide/reference/api/search/uri-request中找到elasticsearch理解的参数列表 感谢@Steve 的回答。我认为这对于一个新问题来说不够重要。它没有在任何地方明确说明,所以我想我会在这里询问只是为了验证。 你真的应该使用扫描+滚动请求。如果您确实使用 size=BIGNUMBER,请注意 Lucene 会为该数字的分数分配内存,因此不要使其过大。 :) Scan 在 2.1.0 中被弃用:elastic.co/guide/en/elasticsearch/reference/current/…【参考方案2】:
http://127.0.0.1:9200/foo/_search/?size=1000&pretty=1
                                   ^

注意 size 参数,它将显示的命中数从默认 (10) 增加到每个分片 1000。

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-from-size.html

【讨论】:

要记住的一件事(来自 Elasticsearch 文档):注意 from + size 不能超过 index.max_result_window 索引设置,默认为 10,000。 这个会返回1000,不是全部,user3078523是对的,这个方法有max_result_window的限制 它有一个最大值,而且(如果你有成千上万条记录要获取)这是一个相当笨重的方法来达到这个最大值。相反,您应该使用“滚动”查询。 你应该将pretty参数作为布尔值传递:curl -XGET 'localhost:9200/logs/_search/?size=1000&pretty=true' 这是我正在寻找的答案。一个没有传递请求参数q。谢谢!【参考方案3】:

elasticsearch(ES) 支持 GET 或 POST 请求从 ES 集群索引中获取数据。

当我们执行 GET 时:

http://localhost:9200/[your index name]/_search?size=[no of records you want]&q=*:*

当我们进行 POST 时:

http://localhost:9200/[your_index_name]/_search

  "size": [your value] //default 10
  "from": [your start index] //default 0
  "query":
   
    "match_all": 
   
   

我建议使用带有弹性搜索的 UI 插件http://mobz.github.io/elasticsearch-head/ 这将帮助您更好地了解您创建的索引并测试您的索引。

【讨论】:

另一位用户提到:from + size 不能超过默认为 10,000 的 index.max_result_window 索引设置 这种方法有一个最大值,而且(如果你有成千上万的记录要获取)这是一个相当笨重的方法来达到这个最大值。相反,您应该使用“滚动”查询 奇怪的是,官方文档显示curl -XGET ... -d '...',这是一个unofficial 混合风格的请求。感谢您显示正确的 GET 和 POST 格式。【参考方案4】:

注意:答案与旧版本的 Elasticsearch 0.90 有关。此后发布的版本具有更新的语法。请参考其他答案,这些答案可能会为您正在寻找的最新答案提供更准确的答案。

下面的查询将返回您希望返回的 NO_OF_RESULTS..

curl -XGET 'localhost:9200/foo/_search?size=NO_OF_RESULTS' -d '

"query" : 
    "match_all" : 
  
'

现在,这里的问题是您希望返回所有记录。所以很自然,在编写查询之前,您不会知道 NO_OF_RESULTS 的值。

我们如何知道您的文档中有多少条记录?只需在下面输入查询

curl -XGET 'localhost:9200/foo/_search' -d '

这会给你一个看起来像下面的结果

 
hits" : 
  "total" :       2357,
  "hits" : [
    
      ..................

结果 total 告诉您文档中有多少记录可用。所以,这是了解 NO_OF RESULTS

值的好方法
curl -XGET 'localhost:9200/_search' -d ' 

在所有索引中搜索所有类型

curl -XGET 'localhost:9200/foo/_search' -d '

在 foo 索引中搜索所有类型

curl -XGET 'localhost:9200/foo1,foo2/_search' -d '

搜索 foo1 和 foo2 索引中的所有类型

curl -XGET 'localhost:9200/f*/_search

在任何以 f 开头的索引中搜索所有类型

curl -XGET 'localhost:9200/_all/type1,type2/_search' -d '

在所有索引中搜索类型用户和推文

【讨论】:

默认情况下 ES 将返回 10 个结果,除非基本查询中包含大小参数。 之前的回复是三年前的。将其更新为当前版本。【参考方案5】:

这是我使用 python 客户端找到的最佳解决方案

  # Initialize the scroll
  page = es.search(
  index = 'yourIndex',
  doc_type = 'yourType',
  scroll = '2m',
  search_type = 'scan',
  size = 1000,
  body = 
    # Your query's body
    )
  sid = page['_scroll_id']
  scroll_size = page['hits']['total']

  # Start scrolling
  while (scroll_size > 0):
    print "Scrolling..."
    page = es.scroll(scroll_id = sid, scroll = '2m')
    # Update the scroll ID
    sid = page['_scroll_id']
    # Get the number of results that we returned in the last scroll
    scroll_size = len(page['hits']['hits'])
    print "scroll size: " + str(scroll_size)
    # Do something with the obtained page

https://gist.github.com/drorata/146ce50807d16fd4a6aa

使用java客户端

import static org.elasticsearch.index.query.QueryBuilders.*;

QueryBuilder qb = termQuery("multi", "test");

SearchResponse scrollResp = client.prepareSearch(test)
        .addSort(FieldSortBuilder.DOC_FIELD_NAME, SortOrder.ASC)
        .setScroll(new TimeValue(60000))
        .setQuery(qb)
        .setSize(100).execute().actionGet(); //100 hits per shard will be returned for each scroll
//Scroll until no hits are returned
do 
    for (SearchHit hit : scrollResp.getHits().getHits()) 
        //Handle the hit...
    

    scrollResp = client.prepareSearchScroll(scrollResp.getScrollId()).setScroll(new TimeValue(60000)).execute().actionGet();
 while(scrollResp.getHits().getHits().length != 0); // Zero hits mark the end of the scroll and the while loop.

https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-search-scrolling.html

【讨论】:

谢谢马克,这正是我想要的!就我而言(ELK 6.2.1,python 3),search_type 参数无效,并且自 ELK 6.0 以来不再需要 document_type 完美解决方案!谢谢。我使用的是elasticsearch_dsl==5.4.0,它在没有search_type = 'scan', 的情况下工作。 ES 6.3。此示例使我的 Elasticsearch 服务崩溃,尝试在第 5 到第 7 次迭代之间滚动带有 size=10000 的 110k 文档。 status=127, main ERROR Null object returned for RollingFile in Appenders, main ERROR Unable to locate appender "rolling" for logger config "root" 没有登录 /var/log/elasticsearch/elasticsearch.log 为了记录,python 客户端实现了一个scan helpers`,它在引擎盖下滚动(至少从版本 5.x.x 开始) search_type = 'scan' 已弃用。没有它,类似的代码也可以工作,尽管在旧文档中隐藏了一些有趣的差异。 elastic.co/guide/en/elasticsearch/reference/1.4/… 特别是,当迁移到不使用 search_type=scan 时,第一个“搜索”查询将与要处理的第一批结果一起出现。【参考方案6】:

如果您只是添加一些大数字作为大小,Elasticsearch 将变得显着变慢,一种用于获取所有文档的方法是使用扫描和滚动 ID。

https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-scroll.html

在 Elasticsearch v7.2 中,您可以这样做:

POST /foo/_search?scroll=1m

    "size": 100,
    "query": 
        "match_all": 
    

由此产生的结果将包含一个 _scroll_id,您必须查询它才能获得下一个 100 块。

POST /_search/scroll 

    "scroll" : "1m", 
    "scroll_id" : "<YOUR SCROLL ID>" 

【讨论】:

这个答案需要更多更新。 search_type=scan 现在已弃用。所以你应该删除它,但是行为发生了一些变化。第一批数据来自初始搜索调用。您提供的链接确实显示了正确的方法。 我的评论是真的要注意你不能只添加任何数字作为大小,因为它会慢很多。所以我删除了代码示例,人们可以点击链接获取正确的代码。 @WoodyDRN 最好在你的答案中包含代码(即使它变旧了),这样在链接失效时它仍然可用。【参考方案7】:

如果您想提取数千条记录,那么...一些人给出了使用“滚动”的正确答案(注意:有些人还建议使用“search_type=scan”。这已被弃用,在 v5.1 中)。 0 已删除。你不需要它)

从“搜索”查询开始,但指定“滚动”参数(这里我使用 1 分钟超时):

curl -XGET 'http://ip1:9200/myindex/_search?scroll=1m' -d '

    "query": 
            "match_all" : 
    

'

这包括您的第一批“命中”。但我们还没有在这里完成。上面 curl 命令的输出是这样的:

  “_ scroll_id”: “c2Nhbjs1OzUyNjE6NU4tU3BrWi1UWkNIWVNBZW43bXV3Zzs1Mzc3OkhUQ0g3VGllU2FhemJVNlM5d2t0alE7NTI2Mjo1Ti1TcGtaLVRaQ0hZU0FlbjdtdXdnOzUzNzg6SFRDSDdUaWVTYWF6YlU2Uzl3a3RqUTs1MjYzOjVOLVNwa1otVFpDSFlTQWVuN211d2c7MTt0b3RhbF9oaXRzOjIyNjAxMzU3Ow ==”, “发生”:109, “TIMED_OUT”:假, “_碎片”: “总”:5, “成功”:5, “失败”:0, "命中":"total":22601357,"max_score":0.0,"命中":[]

拥有 _scroll_id 很重要,因为接下来您应该运行以下命令:

    curl -XGET  'localhost:9200/_search/scroll'  -d'
    
        "scroll" : "1m", 
        "scroll_id" : "c2Nhbjs2OzM0NDg1ODpzRlBLc0FXNlNyNm5JWUc1" 
    
    '

但是,传递 scroll_id 并不是为了手动完成而设计的。你最好的选择是编写代码来做到这一点。例如在java中:

    private TransportClient client = null;
    private Settings settings = ImmutableSettings.settingsBuilder()
                  .put(CLUSTER_NAME,"cluster-test").build();
    private SearchResponse scrollResp  = null;

    this.client = new TransportClient(settings);
    this.client.addTransportAddress(new InetSocketTransportAddress("ip", port));

    QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
    scrollResp = client.prepareSearch(index).setSearchType(SearchType.SCAN)
                 .setScroll(new TimeValue(60000))                            
                 .setQuery(queryBuilder)
                 .setSize(100).execute().actionGet();

    scrollResp = client.prepareSearchScroll(scrollResp.getScrollId())
                .setScroll(new TimeValue(timeVal))
                .execute()
                .actionGet();

现在 LOOP 在最后一条命令上使用 SearchResponse 来提取数据。

【讨论】:

【参考方案8】:

使用server:9200/_stats 还可以获取有关所有别名的统计信息。例如每个别名的大小和元素数量,这非常有用并提供有用的信息

【讨论】:

但是,据我记得,ES 只允许每个请求获取 16000 个数据。所以如果数据在16000以上,这个方案是不够的。【参考方案9】:

如果是小数据集(例如 1K 条记录),您可以简单地指定size

curl localhost:9200/foo_index/_search?size=1000

不需要match all query,因为它是隐含的。

如果你有一个中等大小的数据集,比如 1M 条记录,你可能没有足够的内存来加载它,所以你需要一个scroll。

滚动就像数据库中的游标。在 Elasticsearch 中,它会记住您离开的位置并保持索引的相同视图(即阻止搜索者使用 refresh 离开,阻止 segments from merging)。

API 方面,您必须在第一个请求中添加滚动参数:

curl 'localhost:9200/foo_index/_search?size=100&scroll=1m&pretty'

你得到第一页和一个滚动 ID:


  "_scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAADEWbmJlSmxjb2hSU0tMZk12aEx2c0EzUQ==",
  "took" : 0,
...

请记住,您返回的滚动 ID 和超时都对下一页有效。这里的一个常见错误是指定一个非常大的超时(值为scroll),这将涵盖处理整个数据集(例如 1M 条记录)而不是一页(例如 100 条记录)。

要获取下一页,请填写最后一个滚动 ID 和一个超时,该超时应持续到获取下一页:

curl -XPOST -H 'Content-Type: application/json' 'localhost:9200/_search/scroll' -d '
  "scroll": "1m",
  "scroll_id": "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAADAWbmJlSmxjb2hSU0tMZk12aEx2c0EzUQ=="
'

如果您有很多要导出的内容(例如 1B 文档),您需要并行化。这可以通过sliced scroll 完成。假设您要在 10 个线程上导出。第一个线程会发出这样的请求:

curl -XPOST -H 'Content-Type: application/json' 'localhost:9200/test/_search?scroll=1m&size=100' -d '
  "slice": 
    "id": 0, 
    "max": 10 
  
'

您将返回第一页和滚动 ID,这与普通滚动请求完全一样。您可以像使用普通滚动一样使用它,只是您获得了 1/10 的数据。

其他线程也会这样做,除了 id 将是 1、2、3...

【讨论】:

谢谢,这是我需要了解的(大小);它帮助我解决了我的空 ([ ]) 退货问题。【参考方案10】:

调整大小的最佳方法是在 URL 前面使用 size=number

Curl -XGET "http://localhost:9200/logstash-*/_search?size=50&pretty"

注意:可以在此大小中定义的最大值为 10000。对于任何超过一万的值,它希望您使用滚动功能,以最大限度地减少对性能的影响。

【讨论】:

从哪个版本开始出现最大尺寸? 在某种程度上这可能是“最好的”方式,但真的有点点头。如果您有数千条记录,那么最好的方法是“滚动”查询。 使用 from 和 size-方法你会遇到深度分页问题。使用滚动 API 转储所有文档。【参考方案11】:

简单!可以使用sizefrom参数!

http://localhost:9200/[your index name]/_search?size=1000&from=0

然后逐渐更改from,直到获得所有数据。

【讨论】:

如果数据包含很多文档,千万不要使用这种方法......每次进入“下一页”时,Elastic会越来越慢!改用 SearchAfter 此外,如果整体数据大小超过 10 000,则此解决方案将不起作用。选项 size=1000&from=10001 将失败。 确实失败了。参数from + size 不能超过 index.max_result_window 索引设置,默认为 10,000 如果数据包含数千个文档,正确的答案是使用“滚动”查询。 使用fromsize-方法你会遇到深度分页问题。使用滚动 API 转储所有文档。【参考方案12】:

您可以使用_count API 获取size 参数的值:

http://localhost:9200/foo/_count?q=<your query>

返回count:X, ...。提取值“X”,然后进行实际查询:

http://localhost:9200/foo/_search?q=<your query>&size=X

【讨论】:

像这样将大小设置为 X,可能会出现令人惊讶的并发故障:考虑如果在进行计数和设置下一个查询的大小之间添加一条记录会发生什么......但如果你有成千上万的记录要获取,那么这是错误的方法。相反,您应该使用“滚动”查询。【参考方案13】:

来自 Kibana DevTools:

GET my_index_name/_search

  "query": 
    "match_all": 
  

【讨论】:

【参考方案14】:

您实际上不需要将正文传递给match_all,它可以通过对以下 URL 的 GET 请求来完成。这是最简单的形式。

http://localhost:9200/foo/_search

【讨论】:

【参考方案15】:

http://localhost:9200/foo/_search/?大小=1000&pretty=1

您需要指定 size 查询参数,默认为 10

【讨论】:

使用 from 和 size-方法你会遇到深度分页问题。使用滚动 API 转储所有文档。【参考方案16】:

size 参数将显示的点击数从默认值 (10) 增加到 500。

http://localhost:9200/[indexName]/_search?pretty=true&size=500&q=*:*

逐级更改from,获取所有数据。

http://localhost:9200/[indexName]/_search?size=500&from=0

【讨论】:

【参考方案17】:

使用python包elasticsearch-dsl的简单解决方案:

from elasticsearch_dsl import Search
from elasticsearch_dsl import connections

connections.create_connection(hosts=['localhost'])

s = Search(index="foo")
response = s.scan()

count = 0
for hit in response:
    # print(hit.to_dict())  # be careful, it will printout every hit in your index
    count += 1

print(count)

另见https://elasticsearch-dsl.readthedocs.io/en/latest/api.html#elasticsearch_dsl.Search.scan。

【讨论】:

这非常有帮助 - 为我改变了一切,现在我真的希望能在晚上得到结果。【参考方案18】:

使用 kibana 控制台和 my_index 作为索引搜索以下可以贡献。要求索引只返回索引的 4 个字段,您还可以添加大小以指示您希望索引返回多少个文档。从 ES 7.6 开始,您应该使用 _source 而不是 filter 它将响应更快。

GET /address/_search
 
   "_source": ["streetaddress","city","state","postcode"],
   "size": 100,
   "query":
   "match_all": 
       
 

【讨论】:

【参考方案19】:

对于 Elasticsearch 6.x

请求:GET /foo/_search?pretty=true

响应:在 Hits-> total 中,给出文档的计数

    
      "took": 1,
      "timed_out": false,
      "_shards": 
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
      ,
      "hits": 
        "total": 1001,
        "max_score": 1,
        "hits": [
          

【讨论】:

【参考方案20】:
curl -X GET 'localhost:9200/foo/_search?q=*&pretty' 

【讨论】:

【参考方案21】:

默认情况下,Elasticsearch 返回 10 条记录,因此应明确提供大小。

随请求添加大小以获得所需的记录数。

http://host:9200/index_name/_search?pretty=true&size=(记录数)

注意: 最大页面大小不能超过 index.max_result_window 索引设置,默认为 10,000。

【讨论】:

【参考方案22】:

要从所有索引中返回所有记录,您可以这样做:

curl -XGET http://35.195.120.21:9200/_all/_search?size=50&amp;pretty

输出:

  "took" : 866,
  "timed_out" : false,
  "_shards" : 
    "total" : 25,
    "successful" : 25,
    "failed" : 0
  ,
  "hits" : 
    "total" : 512034694,
    "max_score" : 1.0,
    "hits" : [ 
      "_index" : "grafana-dash",
      "_type" : "dashboard",
      "_id" : "test",
      "_score" : 1.0,
       ...

【讨论】:

【参考方案23】:

通过提供大小,elasticSearch 将返回的最大结果为 10000

curl -XGET 'localhost:9200/index/type/_search?scroll=1m' -d '

   "size":10000,
   "query" : 
   "match_all" : 
    
'

之后,你必须使用 Scroll API 来获取结果并获取 _scroll_id 值并将该值放入 scroll_id 中

curl -XGET  'localhost:9200/_search/scroll'  -d'

   "scroll" : "1m", 
   "scroll_id" : "" 
'

【讨论】:

滚动 API 应该从第一个请求开始就使用。【参考方案24】:

如果仍然有人像我一样为某些用例寻找要从 Elasticsearch 检索的所有数据,这就是我所做的。此外,所有数据意味着,所有索引和所有文档类型。我正在使用 Elasticsearch 6.3

curl -X GET "localhost:9200/_search?pretty=true" -H 'Content-Type: application/json' -d'

    "query": 
        "match_all": 
    

'

Elasticsearch reference

【讨论】:

【参考方案25】:

官方文档提供了这个问题的答案!你可以找到它here。


  "query":  "match_all":  ,
  "size": 1

您只需将 size (1) 替换为您想要查看的结果数!

【讨论】:

问题的作者要求的是“所有”结果,而不是预定义的结果数量。虽然发布文档链接很有帮助,但文档没有描述如何实现这一点,您的答案也没有。 使用 from 和 size-方法你会遇到深度分页问题。使用滚动 API 转储所有文档。【参考方案26】:
curl -XGET 'IP/localhost:9200/Index name/type/_search?scroll=10m&pretty' -d '
"query": 
"filtered": 
"query": 
"match_all": 
'

【讨论】:

虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。【参考方案27】:

除了@Akira Sendoh,没有人回答了如何实际获取所有文档。但即使该解决方案在没有日志的情况下也会使我的 ES 6.3 服务崩溃。使用低级 elasticsearch-py 库的唯一对我有用的是通过使用 scroll() api 的 scan helper:

from elasticsearch.helpers import scan

doc_generator = scan(
    es_obj,
    query="query": "match_all": ,
    index="my-index",
)

# use the generator to iterate, dont try to make a list or you will get out of RAM
for doc in doc_generator:
    # use it somehow

然而,如今更简洁的方式似乎是通过 elasticsearch-dsl 库,它提供更抽象、更简洁的调用,例如:http://elasticsearch-dsl.readthedocs.io/en/latest/search_dsl.html#hits

【讨论】:

【参考方案28】:

这是完成您想要的查询, (我建议使用 Kibana,因为它有助于更​​好地理解查询)

GET my_index_name/my_type_name/_search

   "query":
      "match_all":
   ,
   size : 20,
   from : 3

要获取所有记录,您必须使用“match_all”查询。

size 是您要获取的记录数(限制类型)。 默认情况下,ES 只会返回 10 条记录

from 就像跳过,跳过前 3 条记录。

如果您想准确获取所有记录,只需使用“总计”字段中的值 从 Kibana 中点击此查询并将其与“size”一起使用后的结果。

【讨论】:

这个查询的限制是size + from 必须小于或等于“i​​ndex.max_result_window”。对于大量文档(默认为 10000+),此查询不适用。【参考方案29】:

使用 Elasticsearch 7.5.1

http://$HOST:9200/$INDEX/_search?pretty=true&q=*:*&scroll=10m&size=5000

如果您还可以使用 &size=$number

指定数组的大小

如果你不知道你的索引

http://$HOST:9200/_cat/indices?v

【讨论】:

【参考方案30】:

您可以使用 size=0 这将返回所有文档 例子

curl -XGET 'localhost:9200/index/type/_search' -d '

   size:0,
   "query" : 
   "match_all" : 
    
'

【讨论】:

这将返回一个累积的信息,而不是命中本身

以上是关于Elasticsearch 查询返回所有记录的主要内容,如果未能解决你的问题,请参考以下文章

ElasticSearch简介——简单查询

〈二〉ElasticSearch的认识:索引类型文档

ElasticSearch - 返回唯一值

Elasticsearch 安装

如何使弹性搜索多匹配模糊搜索始终返回最小数量的结果

Elasticsearch多重匹配在提供空字符串时不返回所有结果