大家好,我是Edison。
相信很多童鞋和我一樣,有點傻傻分不清Term查詢和全文查詢的區別,那麼今天我們就來一起梳理一下。
基於Term的查詢
Term(詞項)是ES中表達語義的最小單位,搜索和利用統計語言模型進行自然語言處理都需要處理Term。
ES中Term Query包含了:
Term Query / Range Query / Exist Query / Prefix Query / Wildcard Query
ES中Term的特點:
特點1:在ES中,Term查詢對輸入不做分詞。換句話說,它會將輸入作爲一個整體,在倒排索引中查找準確的詞項,並且使用相關度算分公式爲每個包含該詞項的文檔進行相關度算分 - 例如“Apple Store”。
可能上面有點難理解,現在我們通過一個實例來理解。
首先,我們先插入幾條示例數據:
POST /products/_bulk { "index":{"_id":1}} { "productID": "XHDK-A-1293-#fJ3", "desc":"iPhone"} { "index":{"_id":2}} { "productID": "KDKE-B-9947-#kL5", "desc":"iPad"} { "index":{"_id":3}} { "productID": "J0DL-X-1937-#pV7", "desc":"MBP"}
然後,我們通過以下Term Query查詢desc爲iPhone的記錄:
POST /products/_search { "query":{ "term": { "desc": { "value": "iPhone" } } } }
當你執行這條查詢後,你會發現,ES居然沒有查到這條記錄,明明我們剛剛插入的就是它啊!
別急,這恰恰是因爲Term查詢不對輸入做分詞,會將輸入作爲一個整體,進而導致我們搜索不到。
我們進一步將上面的查詢改爲以下方式就可以查詢到記錄:將iPhone改爲全小寫的iphone即可。
POST /products/_search { "query":{ "term": { "desc": { "value": "iphone" } } } }
同時,如果我們想實現一個精確匹配,我們可以使用term的keyword關鍵字來實現,如下查詢所示:精確匹配一個productID。這也說明,在ES中通過keyword關鍵字查詢,它也不會做分詞處理。
POST /products/_search { "query":{ "term": { "productID.keyword": { "value": "XHDK-A-1293-#fJ3" } } } }
我們還會發現,Term查詢會返回一個算分:0.9808292,代表匹配的精準度。
特點2:可以使用Constant Score將查詢轉換成一個Filtering,避免算分,並利用緩存,提高性能。
剛剛提到ES會在倒排索引中進行相關性算分,這在一定程度上會帶來一些查詢上的開銷。我們可以通過ConstantScore將Query轉成Filter,來避免相關性算分的開銷,還可以有效利用緩存,提高查詢的效率!
POST /products/_search { "explain": true, "query": { "constant_score": { "filter": { "term": { "productID.keyword": { "value": "XHDK-A-1293-#fJ3" } } } } } }
查詢結果顯示也可以證明它會跳過算分步驟:
基於全文的查詢
基於全文的查詢,ES提供了以下Query(我們在第6篇Query DSL中學習的就是全文查詢):
Match Query / Match Phrase Query / Query String Query
基於全文的查詢具有以下的特點:
特點1:索引和搜索時都會進行分詞,查詢字符串先傳到一個合適的分詞器,然後生成一個待查詢的詞項列表。
特點2:查詢會對每個詞項進行底層的查詢,再將結果進行合併,還會爲每個文檔生成一個算分。
針對這兩個特點,我們通過一個示例來串一下:
例如,查詢“Matrix reloaded”,會查到包括Matrix或者reload的所有結果。
首先,構建一個Match Query:
POST /movies/_search { "query": { "match": { "title": { "query": "Matrix reloaded" } } } }
ES會返回title字段中包括Matrix 或者 reloaded的所有記錄:
其次,如果你希望查詢title字段中同時包含Matrix reloaded,那你可以修改默認的operator爲AND來提高精準度:
POST /movies/_search { "profile": "true", "query": { "match": { "title": { "query": "Matrix reloaded", "operator": "AND" } } } }
然後,如果你希望查詢的是隻要出現Matrix 和 reloaed,其中間可以間隔一些單詞,那麼你也可以使用match phrase 和 slop參數設置分詞出現的最大間隔距離:
POST /movies/_search { "profile": "true", "query": { "match_phrase": { "title": { "query": "Matrix reloaded", "slop": 1 } } } }
最後,這個基於全文的查詢在ES中的基本查詢過程如下所示:
小結
本篇,我們瞭解了ElasticSearch的Term和全文查詢的基本概念及其特點,利用這些特點在指定的場景會有是事半功倍的效果!
參考資料
極客時間,阮一鳴,《ElasticSearch核心技術與實戰》