ELK:如何在Elastic-search中检索超过10000个结果/事件

时间:2017-01-14 22:54:37

标签: elasticsearch scroll pagination get resultset

问题: 通过GET /搜索查询中的搜索检索超过10,000个弹性搜索结果。

GET hostname:port /myIndex/_search { 
    "size": 10000,
    "query": {
        "term": { "field": "myField" }
    }
}

我一直在使用尺寸选项,知道:

  

index.max_result_window = 100000

但是,如果我的查询大小为650,000个文档或更多,那么如何在一个GET中检索所有结果?

我一直在阅读有关SCROLL,FROM-TO和PAGINATION API的内容,但所有这些内容都不会超过10K。

这是Elasticsearch论坛的一个例子,我一直在使用:

GET /_search?scroll=1m

任何人都可以提供一个示例,您可以在其中检索GET搜索查​​询的所有文档吗?

非常感谢。

11 个答案:

答案 0 :(得分:19)

如果您想要检索大量文档,那么Scroll就是您的选择,因为它超过10000默认限制,可以提升。

第一个请求需要指定您要进行的查询以及scroll参数,其持续时间为before the search context times out(下例中为1分钟)

POST /index/type/_search?scroll=1m
{
    "size": 1000,
    "query": {
        "match" : {
            "title" : "elasticsearch"
        }
    }
}

在第一次通话的回复中,您需要使用_scroll_id进行第二次通话:

POST /_search/scroll 
{
    "scroll" : "1m", 
    "scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ==" 
}

在每个后续回复中,您将获得一个新的_scroll_id,您需要在下次调用时使用该# first request response = request('POST /index/type/_search?scroll=1m') docs = [ response.hits ] scroll_id = response._scroll_id # subsequent requests while (true) { response = request('POST /_search/scroll', scroll_id) docs.push(response.hits) scroll_id = response._scroll_id } ,直到您检索到所需的文档数量为止。

所以在伪代码中看起来有点像这样:

navbar-brand

答案 1 :(得分:8)

请注意,from + size不能超过index.max_result_window索引设置,该设置默认为10,000。

https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-request-from-size.html

因此,您将在此处有两个申请:

1。向您的查询添加“ track_total_hits ”: true 变量。

GET index/_search
{
    "size":1,
    "track_total_hits": true
}

2。使用Scroll API,但是您不能以常规方式执行from,size的操作,因此必须使用Scroll API。

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

例如:

 POST /twitter/_search?scroll=1m
{
"size": 100,
"query": {
    "match" : {
        "title" : "elasticsearch"
    }
}
}

答案 2 :(得分:1)

另一个选项是search_after标签。结合排序机制,您可以将最后一个元素保存在第一个返回中,然后要求在最后一个元素之后得到结果。

    GET twitter/_search
    {
     "size": 10,
        "query": {
            "match" : {
                "title" : "elasticsearch"
            }
        },
        "search_after": [1463538857, "654323"],
        "sort": [
            {"date": "asc"},
            {"_id": "desc"}
        ]
    }

为我工作。但是到目前为止,获得超过10.000个Dokuments确实不容易。

答案 3 :(得分:1)

使用elascticsearch

nodeJS滚动示例:

<script src="https://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/6.11.5/sweetalert2.all.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/7.0.0/sweetalert2.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/7.0.0/sweetalert2.min.js"></script>
<button id="something" onclick="openSwal();">Open Sweet Alert</button>

答案 4 :(得分:1)

您要去的地方

GET /_search
{
  "size": "10000",
    "query": {
        "match_all": {"boost" : "1.0" }
    }
}

但是我们应该避免使用这种方法一次检索大量文档,因为它会增加数据使用量和开销。

答案 5 :(得分:1)

您可以使用滚动来检索10000多个记录。下面是实现滚动的Python函数示例。

self._elkUrl = "http://Hostname:9200/logstash-*/_search?scroll=1m"
self._scrollUrl="http://Hostname:9200/_search/scroll"
 """
    Function to get the data from ELK through scrolling mechanism
    """ 
    def GetDataFromELK(self):
        #implementing scroll and retrieving data from elk to get more than 100000 records at one search
        #ref :https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-request-scroll.html
        try :
            dataFrame=pd.DataFrame()
            if self._elkUrl is None:
                raise ValueError("_elkUrl is missing")
            if self._username is None:
                raise ValueError("_userNmae for elk is missing")
            if self._password is None:
                raise ValueError("_password for elk is missing")
            response=requests.post(self._elkUrl,json=self.body,auth=(self._username,self._password))
            response=response.json()
            if response is None:
                raise ValueError("response is missing")
            sid  = response['_scroll_id']
            hits = response['hits']
            total= hits["total"]
            if total is  None:
                raise ValueError("total hits from ELK is none")
            total_val=int(total['value'])
            url = self._scrollUrl
            if url is None:
                raise ValueError("scroll url is missing")
            #start scrolling 
            while(total_val>0):
                #keep search context alive for 2m
                scroll = '2m'
                scroll_query={"scroll" : scroll, "scroll_id" : sid }
                response1=requests.post(url,json=scroll_query,auth=(self._username,self._password))
                response1=response1.json()
                # The result from the above request includes a scroll_id, which should be passed to the scroll API in order to retrieve the next batch of results
                sid = response1['_scroll_id']
                hits=response1['hits']
                data=response1['hits']['hits']
                if len(data)>0:
                    cleanDataFrame=self.DataClean(data)
                    dataFrame=dataFrame.append(cleanDataFrame)
                total_val=len(response1['hits']['hits'])
                num=len(dataFrame)
            print('Total records recieved from ELK=',num)
            return dataFrame
        except Exception as e:
            logging.error('Error while getting the data from elk', exc_info=e)
            sys.exit()

答案 6 :(得分:1)

升级 10000 个限制

PUT _settings
{
  "index.max_result_window": 500000
}

答案 7 :(得分:0)

我可以建议一种更好的方法。我想您正在尝试获取超过10,000条记录。尝试以下方式,您还将获得数百万条记录。

  1. 定义您的客户。

    client = Elasticsearch(['http://localhost:9200'])
    
  2. search = Search(using=client)

  3. 检查总点击数。

    results = search.execute()
    results.hits.total
    
  4. s = Search(using=client)

  5. 写下您的查询。

    s = s.query(..write your query here...)
    
  6. 通过扫描将数据转储到数据帧中。扫描会将所有数据转储到您的数据帧中,即使数据量达到数十亿,也要小心。

    results_df = pd.DataFrame((d.to_dict() for d in s.scan()))
    
  7. 看看您的数据框。

    results_df
    
  8. 如果您在使用搜索功能时遇到错误,请执行以下操作:

    from elasticsearch_dsl import Search
    

答案 8 :(得分:0)

search_after documentation

在Ruby中作为哈希查询的示例:

query = {
  size: query_size,
  query: {
    multi_match: {
      query: "black",
      fields: [ "description", "title", "information", "params" ]
    }
  },
  search_after: [after],
  sort: [ {id: "asc"} ]

}

答案 9 :(得分:0)

当结果超过10000个时,获得其余结果的唯一方法是将查询拆分为多个具有更严格过滤条件的更精细的查询,以使每个查询返回的结果少于10000个。然后结合查询结果以获得完整的目标结果集。

此结果限制为10000个结果,适用于以ElasticSearch索引为后盾的Web服务,并且没有办法解决,必须在不使用ElasticSearch的情况下重新实现该Web服务。

答案 10 :(得分:0)

对于Node.js,从ElasticSeach v7.7.0开始,现在有了滚动助手!

此处的文档:https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/7.x/client-helpers.html#_scroll_documents_helper

否则,Scroll API的主要文档都有一个很好的示例可用于:https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/scroll_examples.html