多字段搜索(Multifield Search)
本文翻譯自官方指南的Multifield Search一章。
查詢很少是只擁有一個match查詢子句的查詢。我們經常需要對一個或者多個字段使用相同或者不同的查詢字符串進行搜索,這意味着我們需要將多個查詢子句和它們得到的相關度分值以一種有意義的方式進行合並。
也許我們正在尋找一本名為戰爭與和平的書,它的作者是Leo Tolstoy。也許我們正在使用"最少應該匹配(Minimum Should Match)"來搜索ES中的文檔。另外我們也可能會尋找擁有名為John而姓為Smith的用戶。
在本章中我們會討論一些構建多字段搜索的工具,以及如何根據你的實際情況來決定使用哪種方案。
多個查詢字符串(Multiple Query Strings)
處理字段查詢最簡單的方法是將搜索詞條對應到特定的字段上。如果我們知道戰爭與和平是標題,而Leo Tolstoy是作者,那么我們可以簡單地將每個條件當做一個match
子句,然后通過bool
查詢將它們合並:
GET /_search { "query": { "bool": { "should": [ { "match": { "title": "War and Peace" }}, { "match": { "author": "Leo Tolstoy" }} ] } } }
bool
查詢采用了一種"匹配越多越好(More-matches-is-better)"的方法,因此每個match
子句的分值會被累加來得到文檔最終的_score
。匹配兩個子句的文檔相比那些只匹配一個子句的文檔的分值會高一些。
當然,你並不是只能使用match
子句:bool
查詢可以包含任何其他類型的查詢,包括其它的bool
查詢。我們可以添加一個子句來指定我們希望的譯者:
GET /_search { "query": { "bool": { "should": [ { "match": { "title": "War and Peace" }}, { "match": { "author": "Leo Tolstoy" }}, { "bool": { "should": [ { "match": { "translator": "Constance Garnett" }}, { "match": { "translator": "Louise Maude" }} ] }} ] } } }
我們為什么將譯者的查詢子句放在一個單獨的bool
查詢中?所有的4個match
查詢都是should
子句,那么為何不將譯者的查詢子句和標題及作者的查詢子句放在同一層次上呢?
答案在於分值是如何計算的。bool
查詢會運行每個match
查詢,將它們的分值相加,然后乘以匹配的查詢子句的數量,最后除以所有查詢子句的數量。相同層次的每個子句都擁有相同的權重。在上述查詢中,bool
查詢中包含的譯者查詢子句只占了總分值的三分之一。如果我們將譯者查詢子句放到和標題及作者相同的層次上,就會減少標題和作者子句的權重,讓它們各自只占四分之一。
設置子句優先級
上述查詢中每個子句占有三分之一的權重也許並不是我們需要的。相比譯者字段,我們可能對標題和作者字段更有興趣。我們對查詢進行調整來讓標題和作者相對更重要。
在所有可用措施中,我們可以采用的最簡單的方法是boost
參數。為了增加title
和author
字段的權重,我們可以給它們一個大於1
的boost
值:
GET /_search { "query": { "bool": { "should": [ { "match": { "title": { "query": "War and Peace", "boost": 2 }}}, { "match": { "author": { "query": "Leo Tolstoy", "boost": 2 }}}, { "bool": { "should": [ { "match": { "translator": "Constance Garnett" }}, { "match": { "translator": "Louise Maude" }} ] }} ] } } }
以上的title
和k字段的boost
值為2
。 嵌套的bool
查詢自居的默認boost
值為k。
通過試錯(Trial and Error)的方式可以確定"最佳"的boost
值:設置一個boost
值,執行測試查詢,重復這個過程。一個合理boost
值的范圍在1
和10
之間,也可能是15
。比它更高的值的影響不會起到很大的作用,因為分值會被規范化(Normalized)。
單一查詢字符串(Single Query String)
bool
查詢是多字段查詢的中流砥柱。在很多場合下它都能很好地工作,特別是當你能夠將不同的查詢字符串映射到不同的字段時。
問題在於,現在的用戶期望能夠在一個地方輸入所有的搜索詞條,然后應用能夠知道如何為他們得到正確的結果。所以當我們把含有多個字段的搜索表單稱為高級搜 索(Advanced Search)時,是有一些諷刺意味的。高級搜索雖然對用戶而言會顯得更"高級",但是實際上它的實現方式更簡單。
對於多詞,多字段查詢並沒有一種萬能的方法。要得到最佳的結果,你需要了解你的數據以及如何使用恰當的工具。
了解你的數據
當用戶的唯一輸入就是一個查詢字符串時,你會經常碰到以下三種情況:
最佳字段(Best fields)
當搜索代表某些概念的單詞時,例如"brown fox",幾個單詞合在一起表達出來的意思比單獨的單詞更多。類似title和body的字段,盡管它們是相關聯的,但是也是互相競爭着的。文檔在相同的 字段中應該有盡可能多的單詞(譯注:搜索的目標單詞),文檔的分數應該來自擁有最佳匹配的字段。
多數字段(Most fields)
一個用來調優相關度的常用技術是將相同的數據索引到多個字段中,每個字段擁有自己的分析鏈(Analysis Chain)。
主要字段會含有單詞的詞干部分,同義詞和消除了變音符號的單詞。它用來盡可能多地匹配文檔。
相同的文本可以被索引到其它的字段中來提供更加精確的匹配。一個字段或許會包含未被提取詞干的單詞,另一個字段是包含了變音符號的單詞,第三個字段則使用shingle來提供關於單詞鄰近度(Word Proximity)的信息。
以上這些額外的字段扮演者signal的角色,用來增加每個匹配的文檔的相關度分值。越多的字段被匹配則意味着文檔的相關度越高。
跨字段(Cross fields)
對於一些實體,標識信息會在多個字段中出現,每個字段中只含有一部分信息:
- Person:
first_name
和last_name
- Book:
title
,author
和description
- Address:
street
,city
,country
和postcode
此時,我們希望在任意字段中找到盡可能多的單詞。我們需要在多個字段中進行查詢,就好像這些字段是一個字段那樣。
以上這些都是多詞,多字段查詢,但是每種都需要使用不同的策略。我們會在本章剩下的部分解釋每種策略。
from:http://blog.csdn.net/dm_vincent/article/details/41800351#t4