深度分页:
- 一般采用from+size的方式。
- 缺点:
- 效率低。比如from=5000,size=100,es需要在各个分片上匹配排序并得到5000+100条有效数据,然后在结果集中取最后100条结果。
- 最大可查询条数为1W条。ES目前默认支持的skin值max_result_window=10000,当from+size>max_result_window时,ES就会返回错误。
游标查询:
游标查询则解决了上述的深度分页问题。
原理:对某次查询生成一个游标scroll_id,后续的查询只需要根据这个游标去取数据,直至结果集中返回的hits字典为空。
注意:游标查询每次返回一个新字段scroll_id,每次外面做下一次游标查询,我们必须把前一次查询返回的字段scroll_id传递进去(即初始搜索和每个后续滚动请求返回一个新的scroll_id--只有最近的scroll_id才能被使用)
代码:
import json
from elasticsearch import Elasticsearch
hosts = []
es = Elasticsearch(hosts=hosts)
indices = ['indice0', 'indice1']
# Initialize the scroll
page = es.search(
index=','.join(indices),
doc_type='demo',
scroll='2m',#保持游标查询窗口2分钟
search_type='scan',
size=1000,
q='user_id:123 AND type:user' # 填写 Kibana 搜索栏里的 Lucene 查询语法字符串
)
sid = page['_scroll_id']
scroll_size = page['hits']['total']
print 'total scroll_size: ', scroll_size
l = []
# 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
docs = page['hits']['hits']
l += [x['_source'] for x in docs]
批量插入:
from elasticsearch import Elasticsearch,helpers
es = Elasticsearch([{'host': '127.0.0.1', 'port': 9200}])
action = []
helpers.bulk(es,action)