Elasticsearch系列(七)ES數據搜索之原理分析

本文轉載於ES映射和分析

前言

在探究ES數據搜索原理時,先了解下ES的mapping和analysis機制,關於mapping的詳細可以參考之前的文章:Elasticsearch系列(三)mapping詳解

映射(mapping)機制用於進行字段類型確認,將每個字段匹配爲一種確定的數據類型(string, number, booleans, date等)。

分析(analysis)機制用於進行全文文本(Full Text)的分詞,以建立供搜索用的反向索引。

看完本章,你就會明白ES中的文檔的數據是如何進行數據映射,分詞,如何建立全文倒排索引,從而被快速搜索到的原理。

一、確切值和全文搜索

1、差異

在索引中有12個document,只有一個包含日期2014-09-15,但是我們看看下面查詢中的total hits。

GET /_search?q=2014              # 12 個結果
GET /_search?q=2014-09-15        # 還是 12 個結果 !
GET /_search?q=date:2014-09-15   # 1  一個結果
GET /_search?q=date:2014         # 0  個結果 !

Elasticsearch爲對字段類型進行猜測,動態生成了字段和類型的映射關係。返回的信息顯示了date字段被識別爲date類型。_all因爲是默認字段所以沒有在此顯示,不過我們知道它是string類型。

你會期望每一種核心數據類型(strings, numbers, booleans及dates)以不同的方式進行索引,而這點也是現實:在Elasticsearch中他們是被區別對待的。

但是更大的區別在於確切值(exact values)(比如string類型)及全文文本(full text)之間。
這兩者的區別才真的很重要 - 這是區分搜索引擎和其他數據庫的根本差異。

Elasticsearch中的數據可以大致分爲兩種類型:

確切值 及 全文文本。

確切值是確定的,正如它的名字一樣。比如一個date或用戶ID,也可以包含更多的字符串比如username或email地址。

確切值"Foo"和"foo"就並不相同。確切值2014和2014-09-15也不相同。

全文文本,從另一個角度來說是文本化的數據(常常以人類的語言書寫),比如一篇推文(Twitter的文章)或郵件正文。

而對於全文數據的查詢來說,卻有些微妙。我們不會去詢問這篇文檔是否匹配查詢要求?。 但是,我們會詢問這篇文檔和查詢的匹配程度如何?。換句話說,對於查詢條件,這篇文檔的相關性有多高?

我們很少確切的匹配整個全文文本。我們想在全文中查詢包含查詢文本的部分。不僅如此,我們還期望搜索引擎能理解我們的意圖:

一個針對"UK"的查詢將返回涉及"United Kingdom"的文檔

一個針對"jump"的查詢同時能夠匹配"jumped", “jumps”, “jumping"甚至"leap”

“johnny walker"也能匹配"Johnnie Walker”, “johnnie depp"及"Johnny Depp”

"fox news hunting"能返回有關hunting on Fox News的故事,而"fox hunting news"也能返回關於fox hunting的新聞故事。

爲了方便在全文文本字段中進行這些類型的查詢,Elasticsearch首先對文本分析(analyzes),然後使用結果建立一個倒排索引。接下來我們將討論倒排索引及分析過程。


二、倒排索引

Elasticsearch使用一種叫做倒排索引(inverted index)的結構來做快速的全文搜索。倒排索引由在文檔中出現的唯一的單詞列表,以及對於每個單詞在文檔中的位置組成。

例如,我們有兩個文檔,每個文檔content字段包含:

(1)The quick brown fox jumped over the lazy dog
(2)Quick brown foxes leap over lazy dogs in summer

爲了創建倒排索引,我們首先切分每個文檔的content字段爲單獨的單詞(我們把它們叫做詞(terms)或者表徵(tokens))(譯者注:關於terms和tokens的翻譯比較生硬,只需知道語句分詞後的個體叫做這兩個。),把所有的唯一詞放入列表並排序,結果是這個樣子的:

Term Doc_1 Doc_2
Quick X
The X
brown X X
dog X
dogs X
fox X
foxes X
in X
jumped X
lazy X X
leap X
over X X
quick X
summer X
the X

現在,如果我們想搜索"quick brown",我們只需要找到每個詞在哪個文檔中出現即可:

Term Doc_1 Doc_2
brown X X
quick X
----- ------- -----
Total 2 1

兩個文檔都匹配,但是第一個比第二個有更多的匹配項。 如果我們加入簡單的相似度算法(similarity algorithm),計算匹配單詞的數目,這樣我們就可以說第一個文檔比第二個匹配度更高——對於我們的查詢具有更多相關性。

但是在我們的倒排索引中還有些問題:

(1) "Quick"和"quick"被認爲是不同的單詞,但是用戶可能認爲它們是相同的。

(2) “fox"和"foxes"很相似,就像"dog"和"dogs”——它們都是同根詞。

(3) "jumped"和"leap"不是同根詞,但意思相似——它們是同義詞。

上面的索引中,搜索"+Quick +fox"不會匹配任何文檔(記住,前綴+表示單詞必須匹配到)。只有"Quick"和"fox"都在同一文檔中纔可以匹配查詢,但是第一個文檔包含"quick fox"且第二個文檔包含"Quick foxes"。(譯者注:這段真囉嗦,說白了就是單複數和同義詞沒法匹配)

用戶可以合理地希望兩個文檔都能匹配查詢,我們也可以做得更好。

如果我們將詞爲統一爲標準格式,這樣就可以找到不是確切匹配查詢,但是足以相似從而可以關聯的文檔。例如:

(1)“Quick"可以轉爲小寫成爲"quick”。
(2)“foxes"可以被轉爲根形式"fox”。同理"dogs"可以被轉爲"dog"。
(3)“jumped"和"leap"同義就可以只索引爲單個詞"jump”。

現在的索引:

Term Doc_1 Doc_2
brown X X
dog X X
fox X X
in X
jump X X
lazy X X
over X X
quick X X
summer X
the X X

但我們還未成功。我們的搜索"+Quick +fox"依舊失敗,因爲"Quick"的確切值已經不在索引裏,不過,如果我們使用相同的標準化規則處理查詢字符串的content字段,查詢將變成"+quick +fox",這樣就可以匹配到兩個文檔。

這很重要,你只可以找到確實存在於索引中的詞,所以索引文本和查詢字符串都要標準化爲相同的形式。

這個標記化和標準化的過程叫做分詞(analysis)


三、分析和分析器

3.1 分析

分析(analysis)是這樣一個過程:

首先,標記化一個文本塊爲適用於倒排索引單獨的詞(term)然後標準化這些詞爲標準形式,提高它們的“可搜索性”或“查全率”,這個工作是分析器(analyzer)完成的。一個分析器(analyzer)只是一個包裝用於將三個功能放到一個包裏:

(1)字符過濾器

首先字符串經過字符過濾器(character filter),它們的工作是在標記化前處理字符串。字符過濾器能夠去除HTML標記,或者轉換"&“爲"and”。

(2) 分詞器

下一步,分詞器(tokenizer)被標記化成獨立的詞。一個簡單的分詞器(tokenizer)可以根據空格或逗號將單詞分開(譯者注:這個在中文中不適用)。

(3) 標記過濾

最後,每個詞都通過所有標記過濾(token filters),它可以修改詞(例如將"Quick"轉爲小寫),去掉詞(例如停用詞像"a"、“and”、“the"等等),或者增加詞(例如同義詞像"jump"和"leap”)

Elasticsearch提供很多開箱即用的字符過濾器,分詞器和標記過濾器。這些可以組合來創建自定義的分析器以應對不同的需求。


3.2 分析器

Elasticsearch還附帶了一些預裝的分析器,你可以直接使用它們。下面我們列出了最重要的幾個分析器,來演示這個字符串分詞後的表現差異:

"Set the shape to semi-transparent by calling set_trans(5)"

標準分析器

標準分析器是Elasticsearch默認使用的分析器。對於文本分析,它對於任何語言都是最佳選擇(譯者注:就是沒啥特殊需求,對於任何一個國家的語言,這個分析器就夠用了)。它根據Unicode Consortium的定義的單詞邊界(word boundaries)來切分文本,然後去掉大部分標點符號。最後,把所有詞轉爲小寫。產生的結果爲:

set, the, shape, to, semi, transparent, by, calling, set_trans, 5

簡單分析器

set, the, shape, to, semi, transparent, by, calling, set, trans

空格分析器

空格分析器依據空格切分文本。它不轉換小寫。產生結果爲:

Set, the, shape, to, semi-transparent, by, calling, set_trans(5)

語言分析器

特定語言分析器適用於很多語言。它們能夠考慮到特定語言的特性。例如,english分析器自帶一套英語停用詞庫——像and或the這些與語義無關的通用詞。這些詞被移除後,因爲語法規則的存在,英語單詞的主體含義依舊能被理解(譯者注:stem English words這句不知道該如何翻譯,查了字典,我理解的大概意思應該是將英語語句比作一株植物,去掉無用的枝葉,主幹依舊存在,停用詞好比枝葉,存在與否並不影響對這句話的理解。)。

english分析器將會產生以下結果:

set, shape, semi, transpar, call, set_tran, 5

注意"transparent"、"calling"和"set_trans"是如何轉爲詞幹的。

關於前面確切值和全文搜索的差異原因說明,參考:ES分析器使用

3.3 測試分析器

尤其當你是Elasticsearch新手時,對於如何分詞以及存儲到索引中理解起來比較困難。爲了更好的理解如何進行,你可以使用analyze API來查看文本是如何被分析的。在查詢字符串參數中指定要使用的分析器,被分析的文本做爲請求體:

GET /_analyze?analyzer=standard&text=Text to analyze

結果中每個節點在代表一個詞:

{
    "tokens": [
        {
            "token": "text",
            "start_offset": 0,
            "end_offset": 4,
            "type": "<ALPHANUM>",
            "position": 0
        },
        {
            "token": "to",
            "start_offset": 5,
            "end_offset": 7,
            "type": "<ALPHANUM>",
            "position": 1
        },
        {
            "token": "analyze",
            "start_offset": 8,
            "end_offset": 15,
            "type": "<ALPHANUM>",
            "position": 2
        }
    ]
}

token是一個實際被存儲在索引中的詞。position指明詞在原文本中是第幾個出現的。start_offset和end_offset表示詞在原文本中佔據的位置。

附:更多映射相關查看Elasticsearch系列(三)mapping詳解

本文轉載於ES映射和分析

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章