Elasticsearch筆記(5)

搜索機制

搜索的流程圖如下:

搜索的流程圖

1,文檔寫入ES的時候,ES中會存儲兩份數據。一份是文檔的原始數據,即_source中存儲的信息。另一份是通過分詞、過濾等一系列動作之后生成的倒排索引文件,該文件記錄了詞項和文檔的對應關系。

2,用戶對文檔進行搜索,ES接受到用戶的關鍵詞之后到倒排索引中取查找,通過倒排記錄表查找到關鍵詞對應的文檔,然后在通過評分、高亮、排序等處理,返回給用戶。

3,搜索機制解決的是相關度的問題。用戶輸入一個查詢,ES通過計算關鍵詞和文檔之間的相關度,按照評分排序后返回相關度最高的文檔給用戶。

搜索過程

索引的創建、字段映射、文檔的導入等工作參考前文,此處略過。

ES中有了數據就可以進行下一步的搜索了。

ES中的restful的查詢語句要封裝成json對象的形式,稱為查詢DSL語句。

例如查看books索引的全部數據的DSL語句如下:

get books/_search

{

? ? "query":{

? ? ? ? "match_all":{}

}

}

match_all query 會返回所有的文檔,文檔的評分都是1??梢院唽憺?/p>

get books/_search

下面以term query(精確匹配) 為例子進行講解。

term 查詢用來查詢包含指定詞項的文檔。term 查詢不被解析,只有查詢項和文檔中的詞精確匹配到該文檔才會被索引到。應用場景為查詢需要精確匹配的需求。

例如查詢title中含有“思想”的文檔,DSL語句如下:

GET books/_search

{

"from":"0" //從哪條開始

"size":"100" //返回的條數”

"_source":["title","price"], //指定返回的字段,如果不指定,默認返回所有的字段

"min_score":"0.6" //最下評分過濾機制,只有評分大于0.6的文檔才會返回。

"query":{

????????"term":{"title":"思想"}

}

//高亮查詢關鍵字

"highlight":{

"fields":{

"title":{}

}

}

}

全文索引

match query

match query 會對查詢語句進行分詞,分詞后查詢語句中的任何一個詞被匹配到,那么文檔就會被索引到。如果想匹配所有關鍵詞的文檔,可以用and關鍵字連接。例如:

GET books/_search

{

"query":{

? ? "match":{

? ? ? ? "title":{

? ? ? ? ? ? "query":"java"

? ? ? ? ? ? "operator":"and"

}

}

}

}


match一phrase query

match-phrase query 查詢首先會把查詢語句分詞,分詞器可以自定義。同時文檔需要滿足一下兩個條件文檔才會被索引到

1,分詞后的字段要全部出現在目標字段中

2,字段中的詞項順序需要一致

match一phrase


match_phrase_prefix query


multi一match query

multi一match query? 是match的升級版,用于搜索多個字段。例如查詢語句為:“Java編程”,

查詢域為title和description。查詢DSL語句如下:

GET books/_search

"query":{

? ? multi-match:{

? ? ? ? query:"Java編程"

? ? ? ? //指定查詢的字段,*_name 為通配符的形式

? ? ? ? fields:["title","description","*_name"]

}

}

common_terms query

common terms query 是一種在不犧牲性能的情況下替代停用詞提高搜索準確率和召回率

的方案。

query_string query

query string query 是與Lucene 查詢語句的語法結合非常緊密的一種查詢,允許在一個查

詢語句中使用多個特殊條件關鍵字( 如:AND|OR|NOT ) 對多個字段進行查詢,建議熟悉

Lucene 查詢語法的用戶去使用。

詞項查詢


term query? ?

上文講過了,不在贅述

terms 查詢

如下,查詢北京和西安的數據

{

? "query": {

? ? "terms": {

? ? ? "city": [

? ? ? ? "北京",

? ? ? ? "西安"

? ? ? ]

? ? }

? }

}

range query

range 用于檢索某一個范圍內的文檔。比如說價格50到100的書籍信息等。range有四個參數

gt:大于(>),查詢范圍的最小值,不包含臨界值

gte: 大于等于(>=)。查詢范圍最小值,包含臨界值。

lt: 小于(<)。查詢范圍的上界,不包含臨界值。

lte:小于等于(<=)

查詢價格50到100的書籍

GET books/_search

{

query:{

? ? "range":{

? ? ? ? "price":{

? ? ? ? ? ? "gt":50,

? ? ? ? ? ? "lte":100

}

}

}

}


exists query

返回字段中至少有一個非空值的文檔。如:

{

? "query": {

? ? "exists": {

? ? ? "field": "ownerName"

? ? }

? }

}

返回結果ownerName不為空的文檔。

prefix query

prefix 查詢用于查詢某個字段中以給定前綴開始的文檔,比如查詢title 中含有以java 為前

綴的關鍵詞的文檔,那么含有java javascript javaee 等所有以java 開頭關鍵詞的文檔都會被

匹配。如

{

? "query": {

? ? "prefix": {

? ? ? "title": "Java"

? ? }

? }

}

wildcard query

通配符查詢。支持單通配符和多通配符的形式。?用來一個字符,*用來匹配一個或者是多個字符。如:

{

? "query": {

? ? "wildcard": {

? ? ? "title": "Java*"

? ? }

? }

}


regexp query

正則匹配。例如需要匹配以W 開頭緊跟著數字的郵政編碼:

{

? "query": {

? ? "regexp": {

? ? ? "postcode": ""W[0-9].*"

? ? }

? }

}

fuzzy query

編輯距離又稱Levenshtein 距離,是指兩個字串之間,由一個轉成另一個所需的最少編輯

操作次數。許可的編輯操作包括將一個字符替換成另一個字符,插入一個字符,刪除一個字符。

fuzzy 查詢就是通過計算詞項與文檔的編輯距離來得到結果的,但是使用fozzy 查詢需要消耗

的資源比較大,查詢效率不高,適用于需要模糊查詢的場景。舉例如下,用戶在輸入查詢關鍵

詞時不小心把“javascript ” 拼成“javascritp ” ,在存在拼寫錯誤的情況下使用模糊查詢仍然可

以搜索到含有“javascript ” 的文檔,查詢語句如下:

{

? "query": {

? ? "fuzzy?": {

? ? ? "title": "javascript?"

? ? }

? }

}


type query

type query 用于查詢具有指定類型的文檔。例如查詢Elasticsearch 中type 為IT 的文檔,查

詢語句如下:

{

? "query": {

? ? "type": {

? ? ? "value": "IT"

? ? }

? }

}


ids query

ids query 用于查詢具有指定id 的文檔。。例如,查詢類型為IT, id 為1 、3 、5

的文檔,查詢語句如下:

{

? "query": {

? ? "ids": {

? ? ? "type": "IT",

? ? ? ? "values":["1","3","5"]

? ? }

? }

}


復合查詢

復合查詢就是把一些簡單查詢組合在一起實現更復雜的查詢需求,除此之外復合查詢還

可以控制另外一個查詢的行為。

constan_score


constant score query 可以包裝一個其他類型的查詢,并返回匹配過濾器中的查詢條件且具

有相同評分的文檔。下面的查詢語句會返回title 字段中含有關鍵詞“java ” 的文檔,所有文檔

的評分都是1.2:

{

? "query": {

? ? "constantscore": {

? ? ? ? "filter":{

? ? ? ? ? ? "term":{"title":"java"}

? ? ? ? ?}

? ? ? ? "boost":"1.2"

? ? ? ?}

? ?}

}

bool

bool查詢可以把任意多個簡單查詢組合在一起。使用must、should、must_not、filter選項來表達各個簡單查詢之間的邏輯組合關系。每個選項都可以出現0次或者是多次。

must:文檔必須匹配must選項下的查詢條件。相當于邏輯運算的and

should:文檔可以匹配should選項下的查詢條件也可以不匹配。相當于邏輯運算的or。

must_not:于must相反。匹配到must_not查詢條件的文檔不會被返回。相當于邏輯運算的not

filter:功能和must類似。區別在于filter只起到過濾的作用,不對文檔進行評分。

假設要查詢title 中包含關鍵詞java, 并且price 不能高于70, description 可以包含也可以

不包含虛擬機的書籍, 構造bool 查詢語句如下:

GET books/ search

"query": {

? ? ? ?"bool": {

????????????"minimum—should一match": 1,}

????????"must": {

????????????"match": { "title": "java"}}

????????"should": [

????????????????{"match": { "description": " 虛擬機" }}]

? ? ? ? must_not": {

????????"range": {"price": {"gte": 70}}

????}

}


dis_max

dis max與bool query 有一定聯系也有一定區別,dis max query 支持多并發查詢。

可返回與任意查詢條件子句匹配的任何文檔類型。與bool 查詢可以將所有匹配查詢的分數相

結合使的方式不同,dis 查詢只使用最佳匹配查詢條件的分數

fonction_score

fonction_score query 可以修改查詢的文檔得分,這個查詢在有些情況下非常有用,比如通

過評分函數計算文檔得分代價較高,可以改用過濾器加自定義評分函數的方式來取代傳統的評

分方式。

使用fiinction score query , 用戶需要定義一個查詢和一至多個評分函數,評分函數會對查

詢到的每個文檔分別計算得分。

boosting

boosting 查詢用于需要對兩個查詢的評分進行調整的場景,boosting 查詢會把兩個查詢封

裝在一起并降低其中一個查詢的評分

indices

indices query 適用于需要在多個索引之間進行查詢的場景,它允許指定一個索引名字列表

和內部查詢。indices query 中有query 和no match query 兩部分,query 中用于搜索指定索引

列表中的文檔,no_match_query 中的查詢條件用于搜索指定索引列表之外的文檔。

嵌套查詢

在Elasticsearch 這樣的分布式系統中執行全SQL 風格的連接查詢代價昂貴,是不可行的。

相應地,為了實現水平規模地擴展,Elasticsearch 提供了以下兩種形式的join:

nested query (嵌套查詢)

文檔中可能包含嵌套類型的字段,這些字段用來索引一些數組對象,每個對象都可以作為

一條獨立的文檔被查詢出來。

has child query (有子查詢)和has_parent query (有父查詢)

父子關系可以存在單個的索引的兩個類型的文檔之間。has_child 查詢將返回其子文檔能滿

足特定查詢的父文檔,而has_parent 則返回其父文檔能滿足特定查詢的子文檔。


has_child

現在有兩個索引:員工employee和城市(branch)。類似于數據的兩張表。在ES中,員工是child type ,城市是parent type 。需要在映射中聲明如下:

PUT /company

"mappings": {

????????"branch": {},

????????"employee” {"_parent": { "type": "branch"}}

}

通過子文檔查詢父文檔需要使用has_child查詢。例如,搜索1980 年以后出生的員工所在的

城市。

GET company/branch/_search

"query": {

????"has_child": {

????"type": "employee",

????"query": {

????????"range": {"birthday": {"gte": "1980-01-01’ }}


has_parent

通過父文檔查詢子文檔使用has_parent 查詢。比如,搜索哪些employee 工作在UK, 查詢

命令如下:

GET /company/employee/_search

"query": {

????"has_parent": {

????????"paren_type": "branch",

????????"query": {"match": {"country": "UK"}}

}


位置查詢

Elasticsearch 可以對地理位置點geo_point 類型和地理位置形狀geo_shape 類型的數據進行

搜索。

geo_distance、geo_boundin_box、geo_polygon、geo_shape等。需要的時候可以具體的查詢API。

特殊查詢

more_like_this

more_like_this query 可以查詢和提供文本類似的文檔,通常用于近似文本的推薦等場景。

script

Elasticsearch 支持使用腳本進行查詢。

搜索高亮(略)


搜索排序

默認排序

Elasticsearch 是按照查詢和文檔的相關度進行排序的,默認按評分降序排序。

對于match_all query 而言,由于只返回所有文檔,不需要評分,文檔的順序為添加文檔的

順序。如果需要改變match_all query 的文檔返回順序,可以對_doc 進行排序。例如,返回最

后添加的那條文檔, 可以對_doc 降序排序,設置返回文檔條數為1 。

多字段排序

如按照價格降序排序,在根據年份升序排序。

GET books/ search

"sort": [

????{"price": { "order": "desc"} },

????{"year": {"order": "asc"}}]

分片影響評分

ES是在每一個分片上進行單獨評分的,分片的數量會影響到評分的結果。。同時,分詞器也會

影響評分,原因是使用不同的分詞器會使倒排索引中的詞項數發生改變,最終影響評分。



示例是一個SQL和SDL對應的關系

SELECT

? COUNT(1)

FROM

table

WHERE order_type = 'GUARANTEE'

? AND STATUS IN (

? ? 'FAILED',

? ? 'SUCCEEDED',

? ? 'REFUNDED',

? ? 'UNTESTED',

? ? 'UNTRANSFERED',

? ? 'TRANSFERED',

? ? 'SETTLED',

? ? 'APPLYREFUND'

? )

? AND? id = 306472658

? AND time >= "2019-01-01 00:00:00"

? AND time <= "2019-03-31 23:59:59"

SDL:

{

? "bool" : {

? ? "must" : [

? ? ? {

? ? ? ? "term" : {

? ? ? ? ? "id" : {

? ? ? ? ? ? "value" : "306472658",

? ? ? ? ? ? "boost" : 1.0

? ? ? ? ? }

? ? ? ? }

? ? ? },

? ? ? {

? ? ? ? "term" : {

? ? ? ? ? "order_type" : {

? ? ? ? ? ? "value" : "GUARANTEE",

? ? ? ? ? ? "boost" : 1.0

? ? ? ? ? }

? ? ? ? }

? ? ? },

? ? ? {

? ? ? ? "range" : {

? ? ? ? ? "time" : {

? ? ? ? ? ? "from" : "20190101000000",

? ? ? ? ? ? "to" : null,

? ? ? ? ? ? "include_lower" : true,

? ? ? ? ? ? "include_upper" : true,

? ? ? ? ? ? "boost" : 1.0

? ? ? ? ? }

? ? ? ? }

? ? ? },

? ? ? {

? ? ? ? "range" : {

? ? ? ? ? "time" : {

? ? ? ? ? ? "from" : null,

? ? ? ? ? ? "to" : "20190331235959",

? ? ? ? ? ? "include_lower" : true,

? ? ? ? ? ? "include_upper" : true,

? ? ? ? ? ? "boost" : 1.0

? ? ? ? ? }

? ? ? ? }

? ? ? },

? ? ? {

? ? ? ? "terms" : {

? ? ? ? ? "status" : [

? ? ? ? ? ? "FAILED",

? ? ? ? ? ? "SUCCEEDED",

? ? ? ? ? ? "REFUNDED",

? ? ? ? ? ? "UNTESTED",

? ? ? ? ? ? "UNTRANSFERED",

? ? ? ? ? ? "TRANSFERED",

? ? ? ? ? ? "SETTLED",

? ? ? ? ? ? "APPLYREFUND"

? ? ? ? ? ],

? ? ? ? ? "boost" : 1.0

? ? ? ? }

? ? ? }

? ? ],

? ? "disable_coord" : false,

? ? "adjust_pure_negative" : true,

? ? "boost" : 1.0

? }

}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容