在多值字段上使用短語匹配會產生古怪的行爲:html
PUT /my_index/groups/1
{
"names": [ "John Abraham", "Lincoln Smith"] }
運行一個針對Abraham Lincoln的短語查詢:json
GET /my_index/groups/_search
{
"query": { "match_phrase": { "names": "Abraham Lincoln" } } }
使人詫異的是,以上的這份文檔匹配了查詢。即便Abraham以及Lincoln分屬於name數組的兩我的名中。發生這個現象的緣由在於數組在ES中的索引方式。數組
當John Abraham被解析時,它產生以下信息:app
而後當Lincoln Smith被解析時,它產生了:elasticsearch
換言之,ES對以上數組分析產生的詞條列表和解析單一字符串John Abraham Lincoln Smith時產生的結果是同樣的。在咱們的查詢中,咱們查詢鄰接的abraham和lincoln,而這兩個詞條在索引中確實存在而且鄰接,所以查詢匹配了。ide
幸運的是,有一個簡單的方法來避免這種狀況,經過position_offset_gap參數,它在字段映射中進行配置:ui
DELETE /my_index/groups/
PUT /my_index/_mapping/groups
{
"properties": { "names": { "type": "string", "position_offset_gap": 100 } } }
position_offset_gap設置告訴ES須要爲數組中的每一個新元素設置一個誤差值。所以,當咱們再索引以上的人名數組時,會產生以下的結果:spa
如今咱們的短語匹配就沒法匹配該文檔了,由於abraham和lincoln之間的距離爲100。你必需要添加一個值爲100的slop的值才能匹配。htm
短語查詢(Phrase Query)只是簡單地將不含有精確查詢短語的文檔排除在外,而鄰近查詢(Proximity Query) - 一個slop值大於0的短語查詢 - 會將查詢詞條的鄰近度也考慮到最終的相關度_score中。經過設置一個像50或100這樣的高slop值,你能夠排除那些單詞過遠的文檔,可是也給予了那些單詞鄰近的文檔一個更高的分值。索引
下面針對quick dog的鄰近查詢匹配了含有quick和dog的兩份文檔,可是給與了quick和dog更加鄰近的文檔一個更高的分值:
POST /my_index/my_type/_search
{
"query": { "match_phrase": { "title": { "query": "quick dog", "slop": 50 } } } }
{
"hits": [ { "_id": "3", "_score": 0.75, "_source": { "title": "The quick brown fox jumps over the quick dog" } }, { "_id": "2", "_score": 0.28347334, "_source": { "title": "The quick brown fox jumps over the lazy dog" } } ] }
儘管鄰近度查詢(Proximity Query)管用,可是全部的詞條都必須出如今文檔的這一要求顯的過於嚴格了。這個問題和咱們在全文搜索(Full-Text Search)一章的精度控制(Controlling Precision)一節中討論過的相似:若是7個詞條中有6個匹配了,那麼該文檔也許對於用戶而言已經足夠相關了,可是match_phrase查詢會將它排除在外。
相比將鄰近度匹配做爲一個絕對的要求,咱們能夠將它當作一個信號(Signal) - 做爲衆多潛在匹配中的一員,會對每份文檔的最終分值做出貢獻(參考多數字段(Most Fields))。
咱們須要將多個查詢的分值累加這一事實表示咱們應該使用bool查詢將它們合併。
咱們可使用一個簡單的match查詢做爲一個must子句。該查詢用於決定哪些文檔須要被包含到結果集中。能夠經過minimum_should_match參數來去除長尾(Long tail)。而後咱們以should子句的形式添加更多特定查詢。每一個匹配了should子句的文檔都會增長其相關度。
GET /my_index/my_type/_search
{
"query": { "bool": { "must": { "match": { "title": { "query": "quick brown fox", "minimum_should_match": "30%" } } }, "should": { "match_phrase": { "title": { "query": "quick brown fox", "slop": 50 } } } } } }
毫無疑問咱們能夠向should子句中添加其它的查詢,每一個查詢都用來增長特定類型的相關度。