文本分析概述
文本分析使 Elasticsearch 能夠執行全文搜索,搜索結果會返回所有相關的結果,而不僅僅是完全匹配的結果。
如果你搜索“Quick fox jumps”,你可能希望找到包含“A quick brown fox jumps over the lazy dog”的文檔,你也可能希望找到包含相關詞匯(如“fast fox”或“foxes leap”)的文檔。
分析通過分詞實現全文搜索:將文本分解成更小的單元,稱為詞元。在大多數情況下,這些詞元是單獨的單詞。
如果你將短語“the quick brown fox jumps”作為一個單一字符串進行索引,而用戶搜索“quick fox”,那么它不會被視為匹配。然而,如果你對短語進行分詞并將每個單詞分別索引,查詢字符串中的術語就可以單獨查找。這意味著它們可以通過搜索“quick fox”“fox brown”或其他變體來匹配。
分詞使得能夠對單個術語進行匹配,但每個詞元仍然會逐字匹配。這意味著:
? 搜索“Quick”不會匹配“quick”,盡管你可能希望這兩個詞能夠相互匹配。
? 盡管“fox”和“foxes”有相同的詞根,但搜索“foxes”不會匹配“fox”,反之亦然。
? 搜索“jumps”不會匹配“leaps”。盡管它們沒有相同的詞根,但它們是同義詞,意思相近。
為了解決這些問題,文本分析可以將這些詞元規范化為標準格式。這使得你可以匹配那些與搜索詞不完全相同,但仍然足夠相關的詞元。例如:
? “Quick”可以轉換為小寫:“quick”。
? “foxes”可以進行詞干提取,即還原為詞根:“fox”。
? “jump”和“leap”是同義詞,可以索引為同一個詞:“jump”。
為了確保搜索詞能夠按預期匹配這些詞,你可以對查詢字符串應用相同的分詞和規范化規則。例如,搜索“Foxes leap”可以被規范化為搜索“fox jump”。
自定義文本分析
文本分析是由分析器執行的,它是一組規則,控制整個分析過程。
Elasticsearch 包含一個默認的分析器,稱為標準分析器,它在大多數情況下都能很好地工作。
如果你想定制搜索體驗,你可以選擇不同的內置分析器,甚至可以配置一個自定義的分析器。自定義分析器讓你能夠控制分析過程的每一步,包括:
? 在分詞之前對文本進行更改。
? 文本如何轉換為詞元。
? 在索引或搜索之前對詞元進行的規范化更改。
?
索引和搜索分析
文本分析發生在兩個時間點:
索引時間
當文檔被索引時,任何`text`字段的值都會被分析。
搜索時間
在對`text`字段執行全文搜索時,用戶正在搜索的查詢字符串(即用戶輸入的文本)會被分析。搜索時間也被稱為查詢時間。
在每個時間點使用的分析器(或分析規則集)分別被稱為索引分析器或搜索分析器。
索引分析器和搜索分析器如何協同工作
在大多數情況下,索引和搜索時應該使用相同的分析器。這可以確保字段的值和查詢字符串被轉換成相同形式的標記(tokens)。反過來,這可以確保在搜索期間標記能夠按預期匹配。
示例
一個文檔在`text`字段中索引了以下值:
```
The QUICK brown foxes jumped over the dog!
```
字段的索引分析器將值轉換為標記并對其進行規范化。在這個例子中,每個標記代表一個單詞:
```
[ quick, brown, fox, jump, over, dog ]
```
然后這些標記被索引。
稍后,用戶在同一個`text`字段中搜索以下內容:
用戶期望這個搜索能夠匹配之前索引的句子`The QUICK brown foxes jumped over the dog!`。
然而,查詢字符串并不包含文檔原始文本中使用的精確單詞:
? `Quick`vs`QUICK`
? `fox`vs`foxes`
為了應對這種情況,查詢字符串使用相同的分析器進行分析。這個分析器產生了以下標記:
為了執行搜索,Elasticsearch將這些查詢字符串標記與`text`字段中索引的標記進行比較。
?標記 查詢字符串 `text`字段??
?`quick` X X? ? ? ? ? ?
?`brown` X? ? ? ? ? ?
?`fox` X X? ? ? ? ? ?
?`jump` X? ? ? ? ? ?
?`over` X? ? ? ? ? ?
?`dog` X? ? ? ? ? ?
由于字段值和查詢字符串以相同的方式進行了分析,它們產生了類似的標記。標記`quick`和`fox`是精確匹配的。這意味著搜索匹配了包含`"The QUICK brown foxes jumped over the dog!"`的文檔,正如用戶所期望的那樣。
何時使用不同的搜索分析器
雖然不太常見,但在某些情況下,使用不同的索引和搜索分析器是有意義的。為此,Elasticsearch允許你為查詢字符串指定一個單獨的搜索分析器。
通常,只有在使用相同形式的標記對字段值和查詢字符串進行匹配時會創建意外或不相關的搜索結果時,才應該指定一個單獨的搜索分析器。
示例
Elasticsearch被用于創建一個搜索引擎,該引擎只匹配以提供的前綴開頭的單詞。例如,搜索`tr`應該返回`tram`或`trope`,但永遠不會返回`taxi`或`bat`。
一個文檔被添加到搜索引擎的索引中;該文檔在`text`字段中包含一個這樣的單詞:
字段的索引分析器將值轉換為標記并對其進行規范化。在這個例子中,每個標記代表一個可能的單詞前綴:
```
[ a, ap, app, appl, apple]
```
然后這些標記被索引。
稍后,用戶在同一個`text`字段中搜索以下內容:
用戶期望這個搜索只匹配以`appli`開頭的單詞,例如`appliance`或`application`。搜索不應該匹配`apple`。
然而,如果使用字段的索引分析器來分析這個查詢字符串,它會產生以下標記:
```
[ a, ap, app, appl, appli ]
```
當Elasticsearch將這些查詢字符串標記與`apple`索引的標記進行比較時,它會找到多個匹配項。
?標記 `appli` `apple`??
?`a` X X? ? ? ??
?`ap` X X? ? ? ??
?`app` X X? ? ? ??
?`appl` X X? ? ? ??
?`appli` X? ? ? ??
這意味著搜索會錯誤地匹配`apple`。不僅如此,它還會匹配任何以`a`開頭的單詞。
為了解決這個問題,你可以為`text`字段的查詢字符串指定一個不同的搜索分析器。
在這種情況下,你可以指定一個產生單個標記而不是一組前綴的搜索分析器:
這個查詢字符串標記只會匹配以`appli`開頭的單詞的標記,這更符合用戶的搜索期望。
?