一、配置
python == 3.6/3.8
# 更高版本的elasticsearch會出現doc_type被統一成_doc導致舊版陳述句報錯的情況
pip install elasticsearch==7.8.0
二、連接es
from elasticsearch import Elasticsearch
es = Elasticsearch('ip:port')
三、查看索引是否存在,洗掉索引
# 瀏覽器查看索引
# ip:路由地址;port:運行埠(默認9200);index_name:要查看
# 查看所有索引
http://ip:port/_cat/indices?v&pretty
# 查看單個索引
http://ip:port/index_name/_settings?pretty
# python查看elasticsearch是否存在
# es.indices.exists(index="index_name")
# 洗掉索引
# es.indices.delete(index='index_name', ignore=[400, 404])
三、創建索引與映射
# 索引引數設定
# 索引的靜態引數一旦被設定,不能改變;動態引數可以改變
def create_index(es, index_name):
settings = {
'settings':
{
"number_of_shards": 5, # 設定主索引的主分片數,靜態引數
"number_of_replicas": 0, # 設定主索引的副本數,動態引數
"max_result_window": 10000000, # 設定一次檢索最大回傳數量
"track_total_hits": True, # 使最大回傳設定生效的引數
}
}
if es.indices.exists(index_name):
print(u"%s 已存在" % index_name)
else:
es.indices.create(index=index_name, body=settings)
print(index_name + "索引創建成功")
res = es.indices.create(index='index_name', ignore=400)
print(res)
# 創建映射(索引內每一個欄位的設定)
"""
分詞器主要有兩種情況會被使用:
第一種是插入檔案時,將text型別的欄位做分詞然后插入倒排索引,對應analyzer
第二種就是在查詢時,先對要查詢的text型別的輸入做分詞,再去倒排索引搜索,對應search_analyzer
如果想要讓 索引 和 查詢 時使用不同的分詞器,ElasticSearch也是能支持的,只需要在欄位上加上search_analyzer引數
在索引時,只會去看欄位有沒有定義analyzer,有定義的話就用定義的,沒定義就用ES預設的
在查詢時,會先去看欄位有沒有定義search_analyzer,如果沒有定義,就去看有沒有analyzer,再沒有定義,才會去使用ES預設的
"""
mapping = {
'properties': {
# 簡單設定
'title': {
'type': 'string',
'analyzer': 'jieba',
},
# 較復雜的設定
'content': {
'include_in_all': True, # 控制_all查詢時是否需要查詢該欄位,默認True,若是false將不會被_all查詢
'analyzer': 'jieba', # 查詢和索引統一的分詞器
# 'searchAnalyzer': 'jieba', # 單獨設定查詢分詞器
'index': "analyzed", # 控制欄位怎樣建索引或查詢,no不能被查詢;not_analyzed只存盤原始值,不分詞;analyzed分詞存盤
'boost': 2, # 控制該欄位的查詢權重,大于1會增加相對權重
'term_vector': 'with_positions_offsets', # 存盤完整的term vector資訊,包括field terms、position、offset
'type': 'string', # 舊版支持,從ElasticSearch 5.x開始不再支持string,由text和keyword型別替代,
},
}
}
# 設定mapping資訊:可以指定欄位的型別、是否進行分詞、默認值、是否被索引
# 分詞器analyzer和搜索分詞器search_analyzer,ik_max_word為默認的英文分詞器,jieba等其他分詞器需要額外安裝,
result = es.indices.put_mapping(index='index_name', doc_type='doc', body=mapping)
print(result)
四、查詢索引
1、match_all查詢所有
body = {
"query": {
"match_all": {},
},
"size": 50, # size不設定會默認回傳5條
}
result = es.search(index='index_name', doc_type='doc_type', body=body)
2、分詞相關查詢
| 關鍵詞 | keyword型別 | text型別 | 是否支持分詞 |
|---|---|---|---|
| term | 完全匹配 | 查詢條件中關鍵詞不會被分詞,它必須整個關鍵詞和document中的某個分詞匹配,才能搜索到,多個分詞時必須連續,順序不能顛倒, | 是 |
| match | 完全匹配 | match分詞結果和text的分詞結果有相同的即可 | 否 |
| match_phrase | 完全匹配 | match_phrase的分詞結果必須在text欄位分詞中都包含,而且順序必須相同,而且必須都是連續的, | 是 |
| query_string | 完全匹配 | query_string中和match_string基本一樣,區別是它不考慮順序 | 是 |
# term是代表完全匹配,即不進行分詞器分析,檔案中必須包含整個搜索的詞匯
body = {
"query": {
"term": {
"content": "汽車保養"
"from": 1, # 從第幾個開始回傳
"size": 30, # 一次回傳多少個
}
}
}
# match 分詞,部分匹配查詢,包含文本分詞后的一個或多個詞即符合條件
body = {
"query": {
"match": {"title": "寶馬法拉利蘭博基尼"},
},
}
# match_phrase 分詞,完全匹配查詢,包含文本分詞后的所有詞才符合條件,且匹配詞的順序必須完全按照分詞前的順序
# 例如分詞后為寶馬、法拉利、蘭博基尼,匹配順序寶馬必須在法拉利之前,法拉利必須在蘭博基尼之前
body = {
"query": {
"match_phrase": {"title": "寶馬法拉利蘭博基尼"},
},
}
# query_string,分詞,不考慮順序
body = {
"query": {
"query_string": {
"fields": ["title", "content"],
"query": text,
}
}
}
3、bool組合查詢
"""
bool能將多個簡單查詢組合起來,
使用 must、should、must_not、filter 選項來表示簡單查詢之間的邏輯,每個選項都可以出現 0 次到多次,
must:檔案必須匹配,該選項下的查詢條件,相當于邏輯運算的 AND,且參與檔案相關度的評分,
should:檔案可以匹配 should 選項下的查詢條件也可以不匹配,相當于邏輯運算的 OR,且參與檔案相關度的評分,
must_not:與 must 相反,匹配該選項下的查詢條件的檔案不會被回傳;需要注意的是,must_not 陳述句不會影響評分,它的作用只是將不相關的檔案排除,
filter:和 must 一樣,匹配 filter 選項下的查詢條件的檔案才會被回傳,但是 filter 不評分,只起到過濾功能,與 must_not 相反,
"""
# 例子
{
"query": {
"bool": {
"filter": {
"term": { "status": 1 } # 必須status為1,但是不評分
},
"must_not": {
"range": { "price": { "gte": 70 } } # print必須不大于等于70
},
"must": {
"match": { "title": "java" } # 必須模糊匹配標題title包含java的內容
},
"should": [
{
"match": { "description": "虛擬機" } # 如果description包含虛擬機也匹配
},
{
"match": { "content": "計算公式" } # 如果content包含計算公式也匹配
}
]
}
}
}
"""
控制精度
must 陳述句必須匹配,但有多少 should 陳述句應該匹配呢?默認情況下,沒有 should 陳述句是必須匹配的,只有一個例外,那就是當沒有 must 陳述句的時候,至少有一個 should 陳述句必須匹配,
此外可以通過 minimum_should_match 引數控制需要匹配的 should 陳述句的數
計算規則
bool 查詢采用“匹配越多越好(more_matches_is_better)”的機制,因此滿足 must 和 should 子句的檔案將會合并起來計算分值,
在 filter 子句查詢中,分值將會都回傳 0,
must_not 子句并不影響得分,它們存在的意義是排除已經被包含的檔案,
如上所述,bool 查詢的計算得分主要是 must 和 should 子句,它們的計算規則是,把所有符合 must 和 should 的子句得分加起來,然后乘以匹配子句的數量,再除以子句的總數,
"""
# 個人方法記錄:
def diffWordOrQuery(field, size, texts, boolnext=[], boolnext2=[]):
"""
作用: 構建bool查詢query查詢體
field:str.要檢索的欄位
size:int.單次檢索要回傳的數量
texts:list.對檢索文本進行分詞后的詞串列
boolnext:list.bool的下一級key,對每個texts要采取的匹配策略
boolnext2:list.bool的下下一級key,對應match、term、range
"""
if len(boolnext) < len(texts):
for i in range(len(texts) - len(boolnext)):
boolnext.append("should")
if len(boolnext2) < len(texts):
for i in range(len(texts) - len(boolnext2)):
boolnext2.append("should")
body = {
"query": {
"bool": {
},
},
"size": size,
}
for i, text in enumerate(texts):
if text == " ":
continue
method = boolnext[i]
method2 = boolnext2[i]
sonlst = body["query"]["bool"].get(method, None)
if not sonlst:
body["query"]["bool"][method] = {method2: {field: text}}
else:
son = body["query"]["bool"][method]
if type(son) == dict:
for key1, value1 in son.items():
for key2, value2 in value1.items():
body["query"]["bool"][method] = [{key1: {key2: value2}}, {method2: {field: text}}]
else:
son.append({method2: {field: text}})
return body
texts = ["閱讀", "語文", "英語", "數學", "政治"]
boolnext = ["must", "must_not", "must"]
boolnext2 = ["term", "match"]
body = diffWordOrQuery("title", 50, texts, boolnext, boolnext2)
print(body)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/545286.html
標籤:Python
下一篇:04if分支陳述句
