本文首發於公眾號:Hunter後端
原文連結:Python連線es筆記二之查詢方式彙總
上一節除了介紹使用 Python 連線 es,還有最簡單的 query() 方法,這一節介紹一下幾種其他的查詢方式。
以下是本篇筆記目錄:
在上一節中介紹了 query() 的一個簡單範例,如下:
s = Search(using="default").index("exam")
s = s.query("match", name="張三丰")
query() 中接受兩個引數,第一個是欄位查詢的方式,比如這裡是 match,也可以是 term,這個依照查詢的目的來替換。
第二個則是查詢的欄位與值,比如這裡是查詢的 name 欄位為 "張三丰" 的資料。
如果是有多個條件,比如 name="張三丰",address="中國" 的資料,這裡的 = ,並非是完全等於的意思,而是會依照前面的查詢方式,比如 match 或 term 進行類似的分詞或者模糊搜尋。
如果是上面多個條件的查詢,可以直接在後面加上類似的 query():
s = s.query("match", name="張三丰").query("match", address="中國")
這兩個 query() 通過鏈式操作連在一起轉換成 es 語句就是使用 must 將多條件連線在一起,我們可以使用 to_dict() 方式來檢視:
s.to_dict()
# {'query': {'bool': {'must': [{'match': {'name': '張三丰'}}, {'match': {'address': '中國'}}]}}}
如果看過之前我寫過的 Django 系列筆記,應該記得在 Django 裡也有個 Q() 方法的查詢,和這裡的一樣,也是用於條件的聯合,與或非條件都可以實現。
引入方式如下:
from elasticsearch_dsl import Q
但是如果是在 Django 中使用 es 的連線,也是同樣使用 Q() 方法,我們可以使用 as 來區分,這裡我們對於 es 的 Q() 方法可以使用 ES_Q() 來區分:
from elasticsearch_dsl import Q as ES_Q
單個條件的使用 Q() 如下:
s = s.query(ES_Q("match", name="張三丰"))
如下使用 dict 形式的操作也是等效的:
s = s.query(ES_Q({"match": {"name": "張三丰"}}))
對於這兩個條件,如果想要實現它們的與操作:
q1 = ES_Q("match", name="張三丰")
q2 = ES_Q("match", address="中國")
可以如下實現:
s = s.query(q1 & q2)
如果是想實現上面的或操作,可以如下:
s = s.query(q1 | q2)
如果是想取反,直接在條件前加一個 ~
即可:
q1 = ~ES_Q("match", name="張三丰")
s = s.query(q1)
如果是搜尋多欄位,可以如下操作:
q = ES_Q("multi_match", query="中國 張三丰", fields=["name", "address"])
s = s.query(q)
對於 es 中 text 欄位,前面我們介紹過 .keyword
的查詢方式,是將 text 欄位作為一個整體進行查詢,在 ES_Q() 中,以下兩種操作是等效的:
q = ES_Q({"term": {"address.keyword": "中國湖北省"}})
q = ES_Q("term", address__keyword="中國湖北省")
在 es 中的 filter 操作,在 Python 中是一個 filter() 函數,可以直接使用:
q = ES_Q("term", name="張三丰")
s = s.filter(q)
實現大小於的操作範例如下:
q = ES_Q({"range": {"age": {"gte": 21}}})
s = s.query(q)
如果是想取反,除了使用 ~Q(),還可以直接使用 exclude() 函數,這個和 Django 裡的操作也是一樣的:
q = ES_Q("term", name="張三丰")
s = s.exclude(q)
如果是想對返回的結果進行排序操作,直接使用 .sort() 方法。
比如想對 age 欄位排序,正序返回資料,可如下操作:
s = s.sort("age")
如果是想倒序返回,可以如下操作:
s = s.sort("-age")
多欄位排序直接在後面跟上就行:
s = s.sort("-age", "name")
Python 連線 es 進行分頁,可以直接使用 Python 裡的切片操作,比如:
s = s[5:10]
我們可以通過 source() 方法指定返回的欄位:
s = s.source(["name", "address"])
source() 方法還可以接受 includes 和 excludes 引數來指定返回的欄位或者不返回的欄位,這個和 es 的原生處理方式是一致的:
s = s.source(
includes=["address"],
excludes=["name"]
)
extra() 函數接受一些查詢的額外屬性,比如 size 引數決定返回條數,比如 from 引數可以決定從第幾條資料開始返回,sort 引數決定排序方式,以及 _source 引數決定返回的欄位。
比如我們想要返回的資料從第 2 條資料開始,返回兩條,按照 name 欄位進行排序,只返回 name 和 _id 欄位,可以如下操作:
s = Search(using="default").index("exam")
s = s.extra(
sort="name",
_source=["name"],
**{
"from": 1,
"size": 2
}
)
response = s.execute()
前面介紹過獲取符合條件的總數,可以通過 response.hits.total.value 的方式獲得,其實對於 Search(),可以直接使用 count() 函數:
count = s.count()
如果我們想直接執行 kibana 裡執行的命令,可以使用 from_dict() 函數,比如:
s = s.from_dict(
{
"query": {
"term": {
"name": {
"value": "張三丰"
}
}
}
}
)
如果想獲取更多後端相關文章,可掃碼關注閱讀: