在Python中操作Elasticsearch


 原文

啟動ES和停止

或者嵌套對象查詢

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])

超時

全局超時可以設置構造客戶端時(見 Connectiontimeout參數)或在使用每個請求的基礎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'}}}

 

查詢置於 filter 語句內不進行評分或相關度的計算,所以所有的結果都會返回一個默認評分 1 。

 

 

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) ,它可以接受多個其他過濾器作為參數,並將這些過濾器結合成各式各樣的布爾(邏輯)組合。

布爾過濾器編輯

一個 bool 過濾器由三部分組成:

{
   "bool" : {
      "must" :     [],
      "should" :   [],
      "must_not" : [],
   }
}

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'}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM