Elasticsearch提供了基于JSON的DSL(Domain Specific Language)語句來定義查詢條件,其JavaAPI就是在組織DSL條件。
1.DSL查詢
-
葉子查詢(Leaf query clauses):在特定的字段里查詢特定值,屬于簡單查詢。
-
復合查詢(Compound query clauses):以邏輯方式組合多個葉子查詢或者更改葉子查詢的行為方式。
?測試:無條件查詢match_all
#DSL查詢
GET /items/_search
{"query":{"match_all": {}}
}
我們的數量不止10000,但是查詢出來的value只有10000,并且數據只顯示10條?
Elasticsearch默認超過10000條只顯示10000,并且設置了默認分頁的查詢頁數
?
2.葉子查詢
葉子查詢類型有很多,可以在官網查看全部
Query DSL | Elasticsearch Guide [7.12] | Elastic
-
全文檢索查詢(Full Text Queries):利用分詞器對用戶輸入搜索條件先分詞,得到詞條,然后再利用倒排索引搜索詞條。例如:
-
match:單字段
-
multi_match:多字段
-
-
精確查詢(Term-level queries):不對用戶輸入搜索條件分詞,根據字段內容精確值匹配。但只能查找keyword、數值、日期、boolean類型的字段。例如:
-
ids
-
term:精準匹配
-
range:范圍匹配
-
全文檢索查詢
1.match
? "query":{
? ? "match": {
? ? ? "字段名": "搜索條件"
? ? }
? }
#葉子查詢match
GET /items/_search
{"query":{"match": {"name": "牛奶"}}
}
?存在一個_score關聯度打分,返回結果時按照分值降序排列
?
?2.multi_match
? ? "multi_match": {
? ? ? "query": "搜索條件",
? ? ? "fields": ["字段1","字段2"]
? ? }
字段1和字段2是“或”關系,只需要滿足一個即可
#葉子查詢multi_match
GET /items/_search
{"query":{"multi_match": {"query": "賓格瑞","fields": ["name","brand"]}}
}
?
精準匹配?
不做分詞,只根據輸入字段匹配
1.term?
? ? "term": {
? ? ? "字段名": {
? ? ? ? "value": "查詢條件"
? ? ? }
? ? }
#精確查詢term
GET /items/_search
{"query":{"term": {"brand": {"value": "賓格瑞"}}}
}
2.range?
? ? "range": {
? ? ? "price": {
? ? ? ? "gte/gt": 1000,
? ? ? ? "lte/lt": 2000
? ? ? }
? ? }
查詢price 1000-2000
#范圍查詢查詢range
GET /items/_search
{"query":{"range": {"price": {"gte": 1000,"lte": 2000}}}
}
?3.復合查詢
復合查詢=多個葉子查詢
1.算分函數查詢
在使用全文檢索查詢match中返回結果有_score關聯度打分,按照分值降序排列,但是日常瀏覽器搜索中,搜索出來的前幾條往往是廣告,說明_score關聯度打分可控。
function score 查詢中包含四部分內容:
-
原始查詢條件:query部分,基于這個條件搜索文檔,并且基于原始算法打分,原始算分。
-
過濾條件:filter部分,符合該條件的文檔才會重新算分。
-
算分函數:符合filter條件的文檔要根據這個函數做運算,得到的函數算分,有四種函數
-
weight:函數結果是常量
-
field_value_factor:以文檔中的某個字段值作為函數結果
-
random_score:以隨機數作為函數結果
-
script_score:自定義算分函數算法
-
-
運算模式:算分函數的結果、原始查詢的相關性算分,兩者之間的運算方式,包括:
-
multiply:相乘
-
replace:用function score替換query score
-
其它,例如:sum、avg、max、min
-
GET /hotel/_search
{"query": {"function_score": {"query": { .... }, // 原始查詢,可以是任意條件"functions": [ // 算分函數{"filter": { // 條件過濾"term": {"字段": "過濾條件"}},"weight": 10 // 算分權重為2}],"boost_mode": "multipy" // 加權模式,求乘積}}
}
?2.bool查詢
利用邏輯運算來組合一個或多個查詢子句的組合,bool查詢支持的邏輯運算有:
-
must:必須匹配每個子查詢,類似“與”
-
should:選擇性匹配子查詢,類似“或”
-
must_not:必須不匹配,不參與算分,類似“非”
-
filter:必須匹配,不參與算分
與搜索關鍵字無關的查詢盡量采用must_not或filter邏輯運算,避免參與相關性算分。?
GET /items/_search
{"query": {"bool": {"must": [{"match": {"name": "手機"}}],"should": [{"term": {"brand": { "value": "華為" }}},{"term": {"brand": { "value": "小米" }}}],"must_not": [{"range": {"price": {"gte": 2500}}}],"filter": [{"range": {"price": {"lte": 1000}}}]}}
}
?4.排序
GET /indexName/_search
{"query": {"match_all": {}},"sort": [{"排序字段": {"order": "排序方式asc和desc"}}]
}
5.分頁
1.基礎分頁
elasticsearch中通過修改from
、size
參數來控制要返回的分頁結果:
-
from
:從第幾個文檔開始 -
size
:總共查詢幾個文檔
GET /items/_search
{"query": {"match_all": {}},"from": 0, // 分頁開始的位置,默認為0"size": 10, // 每頁文檔數量,默認10"sort": [{"price": {"order": "desc"}}]
}
?2.深度分頁
在面對數據量比較大時,ELasticsearch會采取分片存儲,將數據分成n份,分配到不同的節點上。利于數據的擴展和存儲,但是也會存在問題。
我要查找990-1000的數據,從單體結構上,只需要排序然后找前1000名,就可以獲得990-1000的數據,但是采取分片存儲后,分片1的990-1000是全部數據的990-1000嗎,大概率不是。此時,需要找到所有的分片前1000,然后整合到一起,再排序,這樣就可以找到總數據的990-1000。
那如果我要找9990-10000,是不是就要找到每個分片的前10000名數據在整合排序查找。
查詢分頁深度較大時,匯總數據過多,對內存和CPU會產生非常大的壓力,因此elasticsearch會禁止from+ size
超過10000的請求。
解決深度分頁方案:
-
search after
:分頁時需要排序,原理是從上一次的排序值開始,查詢下一頁數據。官方推薦使用的方式。 -
scroll
:原理將排序后的文檔id形成快照,保存下來,基于快照做分頁。官方已經不推薦使用。
6.高亮?
在瀏覽器搜索Elasticsearch,發現所有的Elasticsearch、Elastic樣式異于其他內容。
對搜索內容進行分詞,對分詞字段打上高亮標簽<em></em>或<strong></strong>
實現:
GET /{索引庫名}/_search
{"query": {"match": {"搜索字段": "搜索關鍵字"}},"highlight": {"fields": {"高亮字段名稱": {"pre_tags": "<em>","post_tags": "</em>"}}}
}