或者嵌套對象查詢
Python Elasticsearch api(官方文檔)
$ brew services start elasticsearch
$ brew services stop elasticsearch
或
elasticsearch // 啟動
control + c // 停止
重啟:
$ brew services restart elasticsearch
啟動后瀏覽
http://localhost:9200
在Python中操作Elasticsearch
安裝Elasticsearch模塊
pip install elasticsearch
忽略
如果elasticsearch返回2XX響應,則API調用被視為成功(並將返回響應)。否則TransportError
將引發(或更具體的子類)的實例 。您可以在“ 例外”中查看其他異常和錯誤狀態。如果您不希望引發異常,則始終ignore
可以使用應忽略的單個狀態代碼或其列表傳遞參數:
from elasticsearch import Elasticsearch es = Elasticsearch() # ignore 400 cause by IndexAlreadyExistsException when creating an index es.indices.create(index='test-index', ignore=400) # ignore 404 and 400 es.indices.delete(index='test-index', ignore=[400, 404])
超時
全局超時可以設置構造客戶端時(見 Connection
的timeout
參數)或在使用每個請求的基礎request_timeout
(以秒的浮點數)的任何API調用的一部分,則此值將得到傳遞給perform_request
連接類的方法:
# only wait for 1 second, regardless of the client's default es.cluster.health(wait_for_status='yellow', request_timeout=1)
響應過濾
該filter_path
參數用於減少elasticsearch返回的響應。例如,僅返回_id
和_type
,這樣做:
result=es.search(index='my_index1',doc_type='test_type1',body={'query':{'match_all':{}}},filter_path=['hits.hits._type','hits.hits._id']) # result=es.search(index='my_index1',doc_type='test_type1',body={'query':{'match_all':{}}},) print(result)
{'hits': {'hits': [{'_type': 'test_type1', '_id': '2'}, {'_type': 'test_type1', '_id': '1'}]}}
它還支持*
通配符以匹配字段名稱的任何字段或部分:
es.search(index='test-index', filter_path=['hits.hits._*'])
或者
result=es.search(index='my_index1',doc_type='test_type1',body={'query':{'match_all':{}}},filter_path=['hits.hits._i*']) #找到以 _i 開頭的內容
{'hits': {'hits': [{'_index': 'my_index1', '_id': '2'}, {'_index': 'my_index1', '_id': '1'}]}}
注意
某些API調用還接受timeout
傳遞給Elasticsearch服務器的參數。此超時是內部的,並不保證請求將在指定時間內結束。
添加數據
from elasticsearch import Elasticsearch # 默認host為localhost,port為9200.但也可以指定host與port es = Elasticsearch() # 添加或更新數據,index,doc_type名稱可以自定義,id可以根據需求賦值,body為內容 如果不寫id值的話會生成一個隨機數的id es.index(index="my_index",doc_type="test_type",id=1,body={"name":"python","addr":"深圳"})
如
{'_index': 'my_index', '_type': 'test_type', '_id': '9K3sSGoBL92egitcUv3j', '_score': 1.0, '_source': {'name': 'c', 'addr': '廣州', 'tittle': '13 c學習', 'age': 13}}
沒有設定id 就生成了這種id值
# 或者:ignore=409忽略文檔已存在異常 es.create(index="my_index",doc_type="test_type",id=1,ignore=409,body={"name":"python","addr":"深圳"}) ---------------------
#刪除數據
delete:刪除指定index、type、id的文檔 es.delete(index='indexName', doc_type='typeName', id='idValue') #當被刪除的文檔不存在的時候會報錯
elasticsearch.exceptions.NotFoundError: NotFoundError(404,
'{"_index":"my_index","_type":"test_type","_id":"13","_version":3,"result":"not_found","_shards":
{"total":2,"successful":1,"failed":0},"_seq_no":6,"_primary_term":1}')
#條件刪除
body = { 'query':{ 'range':{ 'age':{ 'gte':10, 'lte':10 } } } } # es.delete_by_query(index='my_index',body=body)
查詢數據
from elasticsearch import Elasticsearch es = Elasticsearch() # 獲取索引為my_index,文檔類型為test_type的所有數據,result為一個字典類型 result = es.search(index="my_index") # 或者這樣寫:搜索id=1的文檔 result = es.get(index="my_index",doc_type="test_type",id=1) # 打印所有數據 for item in result["hits"]["hits"]: print(item["_source"]) ---------------------
或者
# 或者
body = {
"query":{
"match_all":{}
}
}
result=es.search(index="my_index",body=body) #注意查詢不要使用 es.search(index="my_index",doc_type="test_type",body=body)
for item in result["hits"]["hits"]:
print(item)
print(item["_source"])
constant_score
通常當查找一個精確值的時候,我們不希望對查詢進行評分計算。只希望對文檔進行包括或排除的計算,所以我們會使用 constant_score
查詢以非評分模式來執行
term
查詢並以一作為統一評分。(只查詢 不評分 將分數默認至為1 查詢效率會很高)
最終組合的結果是一個 constant_score
查詢,它包含一個 term
查詢:
body={ 'query':{ 'constant_score': #我們用 constant_score 將 term 查詢轉化成為過濾器 {'filter': {'term': #我們之前看到過的 term 查詢 {'age':11} } } } } result=es.search(index='my_index1',doc_type='test_type1',body=body)
{'_index': 'my_index1', '_type': 'test_type1', '_id': '1', '_score': 1.0, '_source':
{'name': 'wang', 'age': 11, 'hoby': ['music', 'game', 'car'], 'other': {'job': 'python', 'phone_mun': '18700000000'}}}
查詢置於 |
term、terms查詢
term query會去倒排索引中尋找確切的term,它並不知道分詞器的存在,這種查詢適合keyword、numeric、date等明確值的
term:查詢某個字段里含有某個關鍵詞的文檔
body = { "query":{ "term":{ "name":"python" } } } result=es.search(index="my_index",body=body) # print(a) for item in result["hits"]["hits"]: print(item) print(item["_source"])
查詢結果
{'_index': 'my_index', '_type': 'test_type', '_id': '1', '_score': 0.2876821, '_source': {'name': 'python', 'addr': '深圳'}} {'name': 'python', 'addr': '深圳'}
terms:查詢某個字段里含有多個關鍵詞的文檔
body = { "query":{ "terms":{ "name":["python","java"] } } } result=es.search(index="my_index",body=body) # print(a) for item in result["hits"]["hits"]: print(item) print(item["_source"])
結果
{'_index': 'my_index', '_type': 'test_type', '_id': '2', '_score': 1.0, '_source': {'name': 'java', 'addr': '上海'}} {'name': 'java', 'addr': '上海'} {'_index': 'my_index', '_type': 'test_type', '_id': '1', '_score': 1.0, '_source': {'name': 'python', 'addr': '深圳'}} {'name': 'python', 'addr': '深圳'}
match查詢
match query 知道分詞器的存在,會對field進行分詞操作,然后再查詢
body = { "query":{ "match":{ "name":"python java" #它和term區別可以理解為term是精確查詢,這邊match模糊查詢;match會對"python java"分詞為兩個單詞,然后term對認為這是一個單詞 } } } result=es.search(index="my_index",body=body) # print(a) for item in result["hits"]["hits"]: print(item) print(item["_source"])
match_all:查詢所有文檔
GET /customer/doc/_search/ { "query": { "match_all": {} } }
multi_match:可以指定多個字段
body = { "query":{ "multi_match":{ "query":"python", "fields":["name","tittle"] #只要里面一個字段值是 python 既可以 } } } result=es.search(index="my_index",body=body) # print(a) for item in result["hits"]["hits"]: print(item) print(item["_source"])
排序
使用sort實現排序(類似sql):desc 降序,asc升序
ids
body2={ 'query':{ 'ids':{ 'type':'test_type', 'values':['1','2'] ## 搜索出id為1和2d的所有數據 如果沒有id為2的就只展示 1 的數據,或者寫成 'values':[1,2,3]不帶引號的 # 'values':[1,1] 就只展示一次 id為1的數據 } } } result=es.search(index="my_index",body=body2) # print(a) for item in result["hits"]["hits"]: print(item) print(item["_source"])
復合查詢bool
組合過濾器編輯
前面的兩個例子都是單個過濾器(filter)的使用方式。 在實際應用中,我們很有可能會過濾多個值或字段。比方說,怎樣用 Elasticsearch 來表達下面的 SQL ?
SELECT product FROM products WHERE (price = 20 OR productID = "XHDK-A-1293-#fJ3") AND (price != 30)
這種情況下,我們需要 bool
(布爾)過濾器。 這是個 復合過濾器(compound filter) ,它可以接受多個其他過濾器作為參數,並將這些過濾器結合成各式各樣的布爾(邏輯)組合。
j將上邊的轉換成es
b4={ 'query':{ 'bool':{ 'must_not':[{'term':{'price':30 }}], 'should':[{'term':{'price':20}},{'term':{'productID':'XHDK-A-1293-#fJ3'}},] } } } result=es.search(index='my_store',doc_type='products',body=b4)
bool有3類查詢關系,must(都滿足),should(其中一個滿足),must_not(都不滿足)
body2 = { "query":{ "bool":{ "must":[ {'match':{ #注意這must 里邊的條件是不能用term的 用term來查詢會查不出結果 'addr':'上海' }}, {'match':{ 'name':'java' }} ] } } } result=es.search(index="my_index",body=body2) for item in result["hits"]["hits"]: print('111') print(item) print(item["_source"])
范圍查詢
body2={ 'query':{ 'range':{ 'age':{ 'lte':14, 'gte':10 } } } } # 年齡大於等於10 小於等於14 result=es.search(index="my_index",body=body2) # print(result) for item in result["hits"]["hits"]: print(item) print(item["_source"])
前綴查詢
body2={ 'query':{ 'prefix':{ 'name':'p' # 查詢前綴為"p"的所有數據 } } } result=es.search(index="my_index",body=body2) for item in result["hits"]["hits"]: print(item) print(item["_source"])
通配符查詢
body2={ 'query':{ 'wildcard':{ 'name':'*p' # 查詢以"p"為后綴的所有數據 } } } result=es.search(index="my_index",body=body2) for item in result["hits"]["hits"]: print(item) print(it
排序
body2={ 'query':{ 'range':{ 'age':{ 'gte':10, 'lte':20 } # 查詢以"p"為后綴的所有數據 } }, 'sort':{'age':{'order':'desc'} #以年齡降序排列 } } result=es.search(index="my_index",body=body2) for item in result["hits"]["hits"]: print(item) print(item["_source"])
filter_path
響應過濾
# 只需要獲取_id數據,多個條件用逗號隔開 es.search(index="my_index",doc_type="test_type",filter_path=["hits.hits._id"])
{'_id': '5'} {'_id': '8a3lSGoBL92egitcqP1n'} {'_id': '8'} {'_id': '2'} {'_id': '4'} {'_id': '6'} {'_id': '1'}
# 獲取所有數據 es.search(index="my_index",doc_type="test_type",filter_path=["hits.hits._*"])
{'_index': 'my_index', '_type': 'test_type', '_id': '8a3lSGoBL92egitcqP1n', '_score': 1.0, '_source': {'name': 'c', 'addr': '廣州', 'tittle': 'c學習'}} {'_index': 'my_index', '_type': 'test_type', '_id': '8', '_score': 1.0, '_source': {'name': 'c', 'addr': '廣州', 'tittle': '10 c學習', 'age': 10}}
count
執行查詢並獲取該查詢的匹配數
body2={ 'query':{ 'range':{ 'age':{ 'gte':10, 'lte':20 } # 查詢以"p"為后綴的所有數據 } }, } result=es.count(index="my_index",body=body2) print(result) #結果是5
度量類聚合
獲取最大值
body = { "query":{ "match_all":{} }, "aggs":{ # 聚合查詢 "max_age":{ # 最大值的key "max":{ # 最大 "field":"age" # 查詢"age"的最大值 } } } } # result=es.search(index="my_index2",body=body) print(result['aggregations'])
查詢平均值
body = { "query":{ "match_all":{} }, "aggs":{ # 聚合查詢 "avg_age":{ # 平均值的key "avg":{ # 平均 "field":"age" # 查詢"age"的平均值 } } } } # result=es.search(index="my_index2",body=body) print(result['aggregations'])
查詢最小值
body = { "query":{ "match_all":{} }, "aggs":{ # 聚合查詢 "min_age":{ # 平均值的key "min":{ # 平均 "field":"age" # 查詢"age"的平均值 } } } } # result=es.search(index="my_index2",body=body) print(result['aggregations'])
查詢和
body = { "query":{ "match_all":{} }, "aggs":{ # 聚合查詢 "sum_age":{ # 平均值的key "sum":{ # 平均 "field":"age" # 查詢"age"的平均值 } } } } # result=es.search(index="my_index2",body=body) print(result['aggregations'])
_source:當我們希望返回結果只是一部分字段時,可以加上_source
body = { "_source":["name"], "query":{ "match":{ "name":"python"} } } result=es.search(index="my_index",body=body) # print(a) for item in result["hits"]["hits"]: print(item) print(item["_source"])
結果
{'_index': 'my_index', '_type': 'test_type', '_id': '1', '_score': 0.2876821, '_source': {'name': 'python'}} {'name': 'python'}