# ElasticSearch不支持scroll(分页查询)查询
from pyelasticsearch import ElasticSearch
# Elasticsearch支持scroll查询,一般建议使用这个库
from elasticsearch import helpers,Elasticsearch
""" 注意:以上两个库各自在查询或更新传递的参数是不同的 """
# ElasticSearch查询使用方式
ES = ElasticSearch(URL)
res = ES.search(
query,
index=index,
size=size
)
# Elasticsearch查询使用方式
ES = ElasticSearch(URL)
res = ES.search(
body=query,
index=index,
size=size
)
python2.7在使用helpers.scan时一定要注意,有个深抗,必须传递参数 preserve_order=True,不传递这个参数会报错TransportError(400, u'illegal_argument_exception');这个参数表示查询的时候,是否要排序,如果在查询会返回大量数据的情况下,会对返回的scroll中的数据进行排序,很耗费系统性能;但是 python2.7不知为何强制必须使用这个参数,但是官方说明上面这个参数又是可选参数
class MyConnection(RequestsHttpConnection):
def __init__(self, *args, **kwargs):
proxies = kwargs.pop('proxies', {})
super(MyConnection, self).__init__(*args, **kwargs)
self.session.proxies = proxies
# proxies是需要使用代理时使用,在此使用一般都会出错,需要安装requests的socks代理库,具体我别的文章有讲解,请查看
es_client = Elasticsearch(["ip:port"],
connection_class=MyConnection,
proxies={'http': 'socks5://ip:port'},
timeout=60,
max_retries=10,
retry_on_timeout=True)
# python3的使用方式,如果是python2必须传递参数preserve_order=True,不然会报错
datas = helpers.scan(es_client, index=indexs, query=body, size=1000, request_timeout=100, _source=source)
datas为一个迭代器,会极大的节省内存空间
query:为查询条件
index: 可以为单个索引,也可以为索引的list列表
size: 每次迭代的数量
_source: 可以指定查询之后返回那些字段,舍弃无用数据字段,可以加速数据返回的速度,
处理数据时也可以节省内存,类型为list,如:source = ['name']
# 在使用时一定要注意Elasticsearch与ElasticSearch还是有一定的区别的,传递参数不一样
from elasticsearch import Elasticsearch
ES_SEARCH_HOSTURL = 'http://domain:9000/'
ES = Elasticsearch(ES_SEARCH_HOSTURL)
query = {
"query": {
"bool": {
"must": [],
"must_not": []
}
}
}
# index可以为索引的列表或者单个索引,如果是索引的列表,则使用search时不能传递doc_type,也就是如果同时查询多个索引,不能指定文档的类型
def scroll_search(index, query, size, page):
""" 使用scroll查询ES,实现分页查询
:param index: type of list or str
:param query: type of dict,查询条件
:param size: type of int(1-100),指定返回数据中每页的数据条数
:param page: type of int(>0),指定返回第几页数据
:return: 查询结果总数和某页的数据
"""
try:
res = ES.search(
index=index,
scroll='5m', # 查询一次数据在ES中缓存5分钟再销毁
size=size,
body=query,
sort="modified:desc", # sort增加排序功能,多个字段排序可以以逗号隔开
# sort="modified:desc,_score:desc", # 指定某个字段按照升序或者降序排列,modifie为数据字段
# sort="_doc", # ES会计算一个最优的排序方案
# search_type='scan', # 如果不关注排序的话,可以增加该字段,查询速度十分高效,性能比较好
)
except Exception as e:
raise e
else:
sid = res['_scroll_id'] # 获得查询下一条数据的scroll_id
total = res['hits']['total'] # 获取查询结果中总数据的条数
hits = res["hits"]["hits"] # 首次查询返回第一页的结果数据
results = [hit["_source"] for hit in hits]
first_page = 1
while page > first_page:
try:
res = ES.scroll(scroll_id=sid, scroll='2m')
except Exception as e:
raise e
else:
sid = res['_scroll_id']
hits = res["hits"]["hits"]
results = [hit["_source"] for hit in hits]
first_page += 1
return total, results
# terms使用,其中categories为list类型,含义为categories中任何一个满足条件即可
temp = {"terms": {"categories": categories}}
query["query"]["bool"]["must"].append(temp)
""" 功能:从多个索引中查询需要更新的对应数据的id,再更新此数据 """
from elasticsearch import Elasticsearch
ES_SEARCH_HOSTURL = 'http://domain:9000/'
ES = Elasticsearch(ES_SEARCH_HOSTURL)
indexs = [index1, index2]
query = {
"query": {
"bool": {
"must": []
}
}
}
for index in indexs:
try:
res = ES.search(body=query, index=index, doc_type='info')
except Exception as e:
print(e)
# logger.error("Request search_indicator function error. Error: %s" % e)
message = "Internal server error"
results = data_formatter(message=message)
return Response(results, status=500)
else:
if res["hits"]["total"] > 0:
hits = res["hits"]["hits"][0]
update_id = hits["_id"]
try:
# 注意,如果ES为pyelasticsearch的对象,则需要更新的参数传递形式应该为doc= {"revoked": revoked}
ES.update(index=index, doc_type='indicator_info', id=update_id, body={"doc": {"revoked": revoked}})
except Exception as e:
print(e)
message = "Update {} failed".format(id)
results = data_formatter(message=message)
return Response(results, status=500)
else:
results = data_formatter()
return Response(results, status=200)
from datetime import datetime
def get_now_time():
now_time = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.000Z')
return now_time
# 将数据库中过期的revok字段设置为True,以当前时间为准
# 此处注意更新多个字段,必须以分号隔开,并且中间不能有多余的空格
body = {
"script": {
"inline": "ctx._source.revok = params.revok;ctx._source.mod = params.mod;",
"params": {
"revoked": None,
"mod": now_time
},
"lang": "painless"
},
"query": {
"bool": {
"must": [
{"exists": {"field": "date"}},
{"range": {"date": {"lte": now_time}}}
],
}
}
}
# 由于python2没有update_by_query这个方法,所以只能调用原生post请求实现
# python3可以直接调用update_by_query这个方法实现
url = 'http://ip:port/{}/{}/_update_by_query'.format(index, doc) # 参数分别为索引名与文档类型