天天看點

《深入了解ElasticSearch》——3.5 深入了解資料處理

本節書摘來自華章計算機《深入了解elasticsearch》一書中的第3章,第3.5節,作者:[美] 拉斐爾·酷奇(rafa ku) 馬雷克·羅戈任斯基(marek rogoziński)更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

剛開始使用elasticsearch的時候,各種搜尋方式和查詢類型往往會令人感到頭疼。查詢類型之間行為各異,盡管有些差别非常細微,例如範圍查詢和字首查詢。了解這些差别對了解查詢的工作原理至關重要,尤其是要在elasticsearch提供的預設查詢類型之外做些額外事情的時候,例如,處理多語言資訊。

3.5.1 輸入并不總是進行文本分析

在讨論查詢分析之前,我們先使用以下指令建立一個索引:

《深入了解ElasticSearch》——3.5 深入了解資料處理

如你所見,這個索引非常簡單。文檔隻包含一個字段,該字段使用snowball分析器進行處理。現在,我們通過執行下面這個指令來索引一個簡單的文檔:

《深入了解ElasticSearch》——3.5 深入了解資料處理

此時索引中已經有文檔了,我們不妨用一些查詢來做一下測試,請仔細檢視下面的兩個指令:

《深入了解ElasticSearch》——3.5 深入了解資料處理

https://yqfile.alicdn.com/2c83ae5ff1d354edf04562c69814a931c3c6dc3a.png" >

第一個查詢傳回了目标文檔,而第二個查詢沒有傳回任何結果,兩種情況對比懸殊!也許你已經知道(或猜測到)産生這種差異的原因,即該現象與文本分析有關。我們來比較一下,索引中存儲了什麼,又想搜尋到什麼。為實作該目的,可以通過執行下面的指令來使用文本分析(analyze)api:

《深入了解ElasticSearch》——3.5 深入了解資料處理

端點_analyze允許我們檢視elasticsearch是如何處理text參數中的輸入的,同時也能指定要使用哪個分析器(通過analyzer參數)。

前面的指令經elasticsearch處理後會傳回類似下面的結果:

《深入了解ElasticSearch》——3.5 深入了解資料處理

https://yqfile.alicdn.com/a647a68071d2c7f7f1b07e2f07cc48f279e9fb73.png" >

從中可以看到elasticsearch是如何将輸入轉化為詞條流的。請回顧1.1節,并注意這個事實:每個詞條都攜帶了它在原始文本中的位置資訊、類型資訊(盡管使用者對該資訊不感興趣,但是可能會被過濾器使用到)、詞項資訊(即一個詞,它存儲在索引中,在檢索期用于與查詢中的詞項比對)。為什麼原始文本the quick brown fox jumps over the lazy dog被轉化成了這些詞項:quick、brown、fox、jump、over、lazi(這裡發生了有趣的變化),dog,我們可以總結一下snowball分詞器都做了哪些事情:

過濾非重要詞(如the)。

将單詞轉換為詞幹形式(如jump)。

有時會進行糟糕的轉換(如lazi)。

第三種情況看起來并沒有那麼糟,隻要同一個詞的不同形式得到了統一轉化。如果這種事情發生了,詞幹還原的目的就達到了,即elasticsearch會對查詢和索引中的詞項進行比對,而不管它最初的單詞形态如何。現在,回過頭來看看我們的查詢。該查詢旨在搜尋一個簡單的詞項(如這個例子中的jumps),然而索引中并沒有該詞項(索引中隻有jump)。是以,query在搜尋前應該先用分析器進行處理,此時會将jumps轉換為jump,然後再進行搜尋操作。

現在,請看第二個範例:

《深入了解ElasticSearch》——3.5 深入了解資料處理

範例中的兩個查詢看起來很相似,但查詢結果卻大相徑庭。第一個查詢什麼也沒傳回(因為查詢中的lazy文本與索引中的lazi并不相同),而第二個查詢經過分詞器處理,傳回了我們預期的文檔。

3.5.2 範例的使用

所有這些範例都比較有趣,且能從中發現,有些查詢經過了文本分析處理,而有些沒有。對我們來說最重要的事情是,如何自覺利用這些知識改進具體的搜尋應用。

假如要搜尋本書的内容,可能某些使用者會搜尋書中的章節名、地名或某個片段。因為我們沒有自然語言分析工具,是以不能了解使用者輸入的這些短語。然而,從機率的角度來看,與查詢短語在文本上精确比對的文檔應該是使用者最感興趣的。而從另外一個重要名額來看,與使用者輸入短語中詞語精确比對的文檔才是使用者感興趣的。這裡的詞語精确比對既可以是語義上相同也可以是同一個詞的不同形态。

為了示範,我們先用下面的指令建立一個隻包含單字段文檔的索引:

《深入了解ElasticSearch》——3.5 深入了解資料處理

https://yqfile.alicdn.com/d9afb325328b2ee44d90a753d27c342e2bf45afd.png" >

盡管隻有一個字段,但卻使用了兩個分析器進行文本分析處理,這是因為title字段是multi_field類型的緣故,其中對title.org子字段使用了standard分析器,而對title.i18n子字段使用了english分析器(該分詞器會将使用者輸入轉換為詞幹形式)。

如果我們使用如下指令向索引中添加一個文檔:

《深入了解ElasticSearch》——3.5 深入了解資料處理

此時,索引中的title.org字段已有jumps詞項,而title.i18n字段中也有了jump詞項。然後我們執行下面的查詢:

《深入了解ElasticSearch》——3.5 深入了解資料處理

我們的文檔由于跟查詢完美比對而獲得了較高的得分,這歸功于對field.org字段的命中做了權重處理。field.i18n字段的命中也貢獻了部分得分,隻是它對總得分的影響要小很多,因為我們并沒有對該字段的命中做權重處理,它還是預設權值1。

3.5.3 索引期更換分詞器

另外一件值得一提的事情是,在處理多語言資料的時候,可能要在索引期中動态更換分詞器。比如說,我們修改前面的映射,添加_analyzer相關配置:

《深入了解ElasticSearch》——3.5 深入了解資料處理

我們僅做了少許修改,首先是允許elasticsearch在處理文本時根據文本内容決定采用何種分析器。其中,path參數為文檔中的字段名,該字段中儲存了分析器的名稱。其次是移除了field.i18n字段所用分析器的定義。現在,我們可以用下面這條指令來建立索引:

《深入了解ElasticSearch》——3.5 深入了解資料處理

https://yqfile.alicdn.com/bf8d8cdb85e9e36dbefe89763470d87e7881e3dc.png" >

上面的例子中,elasticsearch從索引中提取lang字段的值,并将該值代表的分析器置于目前文檔的文本分析器處理。總之,當你想對不同文檔采用不同分析器時,該設定非常有用(例如,在文檔中移除或保留非重要詞)。

3.5.4 搜尋時更換分析器

也可以在搜尋時更換分詞器,并通過配置analyzer屬性來實作。例如,下面這個查詢:

《深入了解ElasticSearch》——3.5 深入了解資料處理

https://yqfile.alicdn.com/a686c9c986edab401a906138a33d9d5cbba44cd5.png" >

如代碼所示,elasticsearch會采用我們顯式提到過的分析器。

3.5.5 陷阱與預設分析

索引期與檢索期能針對文檔更換分詞器的機制是一個非常有用的特性,但它也會引入很多非常隐蔽的錯誤。其中之一就是沒有定義分析器。針對這種情況,雖然elasticsearch會選用一個所謂的預設分析器,但這往往并不是我們想要的。這是因為預設分析器有時候會被文本分析插件子產品重定義。此時,有必要指定elasticsearch的預設分析器。為了實作該目的,我們還是像平常那樣定義分析器,隻是将自定義分析器的名稱替換為default。

作為一種備選方案,你可以定義default_index分析器和default_search分析器,并将它們作為索引期和檢索期的預設分析器。

繼續閱讀