Azure AI 搜尋中的全文搜索

全文搜索是資訊擷取的方法,與儲存在索引中的純文本相符。 例如,假設查詢字串「海灘上聖迭戈的酒店」,搜尋引擎會根據這些詞彙尋找標記化的字串。 若要讓掃描更有效率,查詢字串會經歷語彙分析:將所有字詞大小寫較低、移除 「the」 等停用字詞,以及將字詞減少為基本根表單。 找到相符字詞時,搜尋引擎會擷取檔、依相關性排序檔,並傳回最上層的結果。

查詢執行可能相當複雜。 本文適用於需要更深入瞭解全文搜索在 Azure AI 搜尋中的運作方式的開發人員。 針對文字查詢,Azure AI 搜尋會在大部分案例中順暢地提供預期的結果,但偶爾您可能會得到看似「關閉」的結果。 在這些情況下,在 Lucene 查詢執行的四個階段中具有背景(查詢剖析、語彙分析、檔比對、評分)可協助您識別產生所需結果之查詢參數或索引組態的特定變更。

注意

Azure AI 搜尋會使用 Apache Lucene 進行全文搜索,但 Lucene 整合並不詳盡。 我們選擇性地公開和擴充 Lucene 功能,以啟用 Azure AI 搜尋很重要的案例。

架構概觀和圖表

查詢執行有四個階段:

  1. 查詢剖析
  2. 語彙分析
  3. 檔擷
  4. 評分

全文搜索查詢會從剖析查詢文字開始,以擷取搜尋字詞和運算符。 有兩個剖析器,可讓您在速度和複雜度之間進行選擇。 接下來是分析階段,其中個別查詢字詞有時會細分並重新組成新形式。 此步驟有助於將更廣泛的網路投向可能相符的專案。 然後搜尋引擎會掃描索引,以尋找具有相符字詞的檔,併為每個相符項目評分。 結果集接著會依指派給每個個別相符檔的相關性分數來排序。 排名清單頂端的那些會傳回給呼叫的應用程式。

下圖說明用來處理搜尋要求的元件。

Lucene query architecture diagram in Azure AI Search.

主要元件 功能描述
查詢剖析器 將查詢詞彙與查詢運算符分開,並建立要傳送至搜尋引擎的查詢結構(查詢樹狀結構)。
分析器 對查詢詞彙執行語彙分析。 此程式可能包括轉換、移除或擴充查詢字詞。
Index 用來儲存及組織從索引檔擷取的可搜尋字詞的有效數據結構。
搜尋引擎 根據反向索引的內容擷取和評分相符的檔。

搜尋要求的剖析

搜尋要求是結果集中應該傳回之專案的完整規格。 最簡單的形式是空的查詢,沒有任何種類的準則。 更現實的範例包括參數、數個查詢詞彙,可能限定於特定欄位,且可能具有篩選表達式和排序規則。

下列範例是您可以使用 REST API 傳送至 Azure AI 搜尋服務的搜尋要求。

POST /indexes/hotels/docs/search?api-version=2020-06-30
{
    "search": "Spacious, air-condition* +\"Ocean view\"",
    "searchFields": "description, title",
    "searchMode": "any",
    "filter": "price ge 60 and price lt 300",
    "orderby": "geo.distance(location, geography'POINT(-159.476235 22.227659)')", 
    "queryType": "full" 
}

針對此要求,搜尋引擎會執行下列作業:

  1. 尋找價格至少為 $60 且小於 $300 的文件。

  2. 執行查詢。 在此範例中,搜尋查詢是由片語和字詞所組成: "Spacious, air-condition* +\"Ocean view\"" (使用者通常不會輸入標點符號,但在範例中包含標點符號,可讓我們說明分析器如何處理它)。

    針對此查詢,搜尋引擎會掃描 「searchFields」 中指定的描述和標題欄位,以尋找包含 "Ocean view"的檔,以及在字詞 "spacious"上,或以前置詞 "air-condition"開頭的字詞。 “searchMode” 參數可用來比對任何字詞(預設值)或全部字詞,以在不需要字詞的情況下(+)。

  3. 依鄰近指定地理位置排序產生的一組旅館,然後將結果傳回給呼叫的應用程式。

本文大部分都是關於處理 搜尋查詢"Spacious, air-condition* +\"Ocean view\""。 篩選和排序範圍不足。 如需詳細資訊,請參閱 搜尋 API 參考檔

階段 1:查詢剖析

如前所述,查詢字串是要求的第一行:

 "search": "Spacious, air-condition* +\"Ocean view\"", 

查詢剖析器會將運算元(例如 和 *+ 在範例中)與搜尋字詞分開,並將搜尋查詢解構為 支援的型別子查詢

  • 獨立字詞的字詞查詢 (如寬大)
  • 引號字詞的片語查詢 (例如遠景)
  • 前置詞查詢 字詞後面接著前置詞運算元 * (例如空調)

如需支持查詢類型的完整清單,請參閱 Lucene 查詢語法

與子查詢相關聯的運算符會判斷查詢 「must」 或 「should be」 是否滿足,以便將文件視為相符專案。 例如, +"Ocean view" 是 「must」 ,因為 + 運算子。

查詢剖析器會將子查詢重新建構為 查詢樹 狀結構(代表查詢的內部結構),其會傳遞給搜尋引擎。 在查詢剖析的第一個階段中,查詢樹狀結構看起來像這樣。

Conceptual diagram of a boolean query with searchmode set to any.

支援的剖析器:簡單和完整 Lucene

Azure AI 搜尋會公開兩種不同的查詢語言( simple 預設值) 和 full。 藉由使用搜尋要求設定 queryType 參數,您可以告訴查詢剖析器您選擇的查詢語言,讓它知道如何解譯運算符和語法。

  • 簡單查詢語言是直覺且健全的,通常適合將使用者輸入解譯為無客戶端處理。 它支援從 Web 搜尋引擎熟悉的查詢運算子。

  • 您可以藉由設定 queryType=full取得的完整 Lucene 查詢語言,藉由新增更多運算元和查詢類型的支援,例如通配符、模糊、regex 和字段範圍查詢,來擴充預設的 Simple 查詢語言。 例如,在Simple查詢語法中傳送的正則表達式會解譯為查詢字串,而不是表達式。 本文中的範例要求會使用 Full Lucene 查詢語言。

searchMode 對剖析器的影響

另一個影響剖析的搜尋要求參數是 「searchMode」 參數。 它會控制布爾查詢的預設運算符:任何 (預設值) 或全部。

當 “searchMode=any”,也就是預設值時,寬闊和空調之間的空格分隔符為 OR (||),讓範例查詢文字相當於:

Spacious,||air-condition*+"Ocean view" 

在中+"Ocean view"+明確運算符在布爾查詢建構中明確無誤(詞彙必須相符)。 較不明顯的是如何解釋其餘術語:寬敞的和空調。 搜尋引擎應該在海濱和寬敞的空調上找到相符專案嗎? 還是應該找到遠景加上 其餘任一 條款?

根據預設(“searchMode=any”),搜尋引擎會假設更廣泛的解譯。 這兩個字段 都應該 相符,以反映 「or」 語意。 先前說明的初始查詢樹狀結構,包含兩個「應該」作業,會顯示預設值。

假設我們現在設定 「searchMode=all」。。 在此情況下,空間會解譯為 「and」 作業。 其餘條款都必須同時存在於檔中,才能符合資格。 產生的範例查詢會解譯如下:

+Spacious,+air-condition*+"Ocean view"

此查詢的修改查詢樹狀結構如下所示,其中相符的檔是這三個子查詢的交集:

Conceptual diagram of a boolean query with searchmode set to all.

注意

在 「searchMode=all」 中選擇 「searchMode=any」 是執行代表性查詢最能到達的決定。 如果 「searchMode=all」 通知布爾查詢建構,可能包含運算子的使用者(在搜尋檔存放區時很常見)可能會發現結果更直覺。 如需 「searchMode」 與運算子之間的互動詳細資訊,請參閱 簡單查詢語法

階段 2:語彙分析

語彙分析器會在結構化查詢樹狀結構之後處理 字詞查詢片語組查詢 。 分析器接受剖析器提供給它的文字輸入、處理文字,然後傳回要併入查詢樹狀結構的標記化字詞。

最常見的語彙分析形式是 *語言分析,可根據特定語言的特定規則來轉換查詢字詞:

  • 將查詢字詞縮減為單字的根形式
  • 移除非基本字詞(英文中的 “the” 或 “and” 等停用字詞)
  • 將複合字分成元件元件
  • 小寫大寫單字

所有這些作業通常會清除使用者所提供的文字輸入與儲存在索引中的字詞之間的差異。 這類作業超越文字處理,而且需要深入了解語言本身。 若要新增這一層語言感知,Azure AI 搜尋支援來自 Lucene 和 Microsoft 的 一長串語言分析器

注意

根據您的案例,分析需求的範圍可能從最小到詳細說明。 您可以藉由選取其中一個預先定義的分析器,或建立您自己的 自定義分析器,來控制語彙分析的複雜度。 分析器的範圍是可搜尋的欄位,並指定為欄位定義的一部分。 這可讓您根據每個欄位來改變語彙分析。 未指定, 會使用標準 Lucene 分析器。

在我們的範例中,在分析之前,初始查詢樹狀結構具有 「Spacious」 一詞,其中包含大寫的 「S」。,以及查詢剖析器解譯為查詢字詞的一部分的逗號(不會將逗號視為查詢語言運算符)。

當預設分析器處理字詞時,它會小寫 「ocean view」 和 「spacious」,並移除逗號字元。 變更過的查詢樹狀結構看起來像:

Conceptual diagram of a boolean query with analyzed terms.

測試分析器行為

分析器的行為可以使用分析 API 進行測試。 提供您想要分析的文字,以查看給定分析器所產生的字詞。 例如,若要查看標準分析器如何處理「空調」文字,您可以發出下列要求:

{
    "text": "air-condition",
    "analyzer": "standard"
}

標準分析器會將輸入文字分成下列兩個標記,以開始和結束位移(用於點擊醒目提示)及其位置(用於片語比對)等屬性加上批註:

{
  "tokens": [
    {
      "token": "air",
      "startOffset": 0,
      "endOffset": 3,
      "position": 0
    },
    {
      "token": "condition",
      "startOffset": 4,
      "endOffset": 13,
      "position": 1
    }
  ]
}

語彙分析的例外狀況

語彙分析僅適用於需要完整詞彙的查詢類型 –字詞查詢或片語查詢。 它不適用於含有不完整字詞的查詢類型 – 前置詞查詢、通配符查詢、regex 查詢 – 或模糊查詢。 這些查詢類型,包括範例中字詞 air-condition* 的前置詞查詢,會直接新增至查詢樹狀結構,略過分析階段。 在這些類型的查詢詞彙上執行的唯一轉換是降低。

階段 3:檔擷取

檔擷取是指在索引中尋找具有相符詞彙的檔。 透過範例可瞭解此階段。 讓我們從具有下列簡單架構的旅館索引開始:

{
    "name": "hotels",
    "fields": [
        { "name": "id", "type": "Edm.String", "key": true, "searchable": false },
        { "name": "title", "type": "Edm.String", "searchable": true },
        { "name": "description", "type": "Edm.String", "searchable": true }
    ] 
} 

進一步假設此索引包含下列四份檔:

{
    "value": [
        {
            "id": "1",
            "title": "Hotel Atman",
            "description": "Spacious rooms, ocean view, walking distance to the beach."
        },
        {
            "id": "2",
            "title": "Beach Resort",
            "description": "Located on the north shore of the island of Kauaʻi. Ocean view."
        },
        {
            "id": "3",
            "title": "Playa Hotel",
            "description": "Comfortable, air-conditioned rooms with ocean view."
        },
        {
            "id": "4",
            "title": "Ocean Retreat",
            "description": "Quiet and secluded"
        }
    ]
}

如何編製字詞的索引

若要瞭解擷取,它有助於瞭解索引編製的一些基本概念。 記憶體單位是反向索引,每個可搜尋欄位各一個。 反向索引內是所有檔中所有字詞的排序列表。 每個字詞都會對應至文件清單,如下列範例所示。

為了在反向索引中產生詞彙,搜尋引擎會針對文件內容執行語彙分析,類似於查詢處理期間所發生的情況:

  1. 根據分析器組態,文字輸入 會傳遞至分析器、小寫、去除標點符號等。
  2. 令牌 是語彙分析的輸出。
  3. 字詞 會新增至索引。

使用相同的分析器進行搜尋和編製索引作業很常見,但並非必要,因此查詢字詞看起來更像是索引內的字詞。

注意

Azure AI 搜尋可讓您指定不同的分析器,以透過其他 indexAnalyzer 和欄位參數編制索引和 searchAnalyzer 搜尋。 如果未指定,則會 analyzer 使用 屬性設定分析器來編製索引和搜尋。

檔範例的反向索引

返回我們的範例,針對 標題 字段,反向索引看起來像這樣:

詞彙 檔案清單
阿特曼 1
海邊 2
酒店 1, 3
海洋 4
花花公子 3
度假村 3
撤退 4

在標題欄位中,只有 旅館 會顯示在兩個檔中:1、3。

針對 [描述] 欄位,索引如下所示:

詞彙 檔案清單
空氣 3
4
海邊 1
條件 3
舒適 3
distance 1
島嶼 2
kauaʻi 2
位於 2
north 2
海洋 1, 2, 3
of 2
on 2
安靜 4
房間 1, 3
僻靜 4
海岸 2
寬敞 1
the 1, 2
打給 1
檢視 1, 2, 3
1
取代為 3

比對索引字詞的查詢字詞

假設上述反轉索引,讓我們回到範例查詢,並查看範例查詢的相符檔如何找到。 回想一下,最終查詢樹狀結構看起來像這樣:

Conceptual diagram of a boolean query with analyzed terms.

在查詢執行期間,個別查詢會針對可搜尋的欄位獨立執行。

  • TermQuery,“寬敞的”,符合檔1(酒店阿特曼)。

  • PrefixQuery“air-condition*” 不符合任何檔。

    這是有時混淆開發人員的行為。 雖然檔中存在空調一詞,但預設分析器會將其分成兩個字詞。 回想一下,不會分析包含部分字詞的前置詞查詢。 因此,在反向索引中會查閱前置詞 「air-condition」 的詞彙,而且找不到。

  • PhraseQuery「海洋檢視」會查閱「海洋」和「檢視」等字詞,並檢查源檔中詞彙的鄰近性。 檔 1、2 和 3 符合描述欄位中的此查詢。 請注意,檔 4 具有標題中的海洋一詞,但不被視為相符專案,因為我們正在尋找「海洋檢視」片語,而不是個別的單字。

注意

除非您使用 參數來限制設定的欄位,否則 Azure AI 搜尋服務索引中的所有可搜尋欄位 searchFields 都會獨立執行搜尋查詢,如範例搜尋要求所示。 會傳回任何所選欄位中相符的檔。

整體而言,針對有問題的查詢,符合的檔為 1、2、3。

階段 4:評分

搜尋結果集中的每個文件都會指派相關性分數。 相關性分數的函式是將那些最能回答用戶問題的檔排名較高,如搜尋查詢所表示。 分數是根據相符詞彙的統計屬性來計算。 評分公式的核心是 TF/IDF(詞彙 frequency-inverse 檔頻率)。 在包含罕見和常見詞彙的查詢中,TF/IDF 會提升包含罕見詞彙的結果。 例如,在具有所有維琪百科文章的假設索引中,從符合總統查詢的檔來看,與總統相符的檔相比,比對的檔更相關。

評分範例

回想一下符合範例查詢的三份檔:

search=Spacious, air-condition* +"Ocean view"  
{
  "value": [
    {
      "@search.score": 0.25610128,
      "id": "1",
      "title": "Hotel Atman",
      "description": "Spacious rooms, ocean view, walking distance to the beach."
    },
    {
      "@search.score": 0.08951007,
      "id": "3",
      "title": "Playa Hotel",
      "description": "Comfortable, air-conditioned rooms with ocean view."
    },
    {
      "@search.score": 0.05967338,
      "id": "2",
      "title": "Ocean Resort",
      "description": "Located on a cliff on the north shore of the island of Kauai. Ocean view."
    }
  ]
}

檔 1 最符合查詢,因為描述 欄位中同時出現寬大 片語和必要的片語 海洋檢視 。 接下來的兩份檔只符合海洋檢視的片語。 即使檔 2 和 3 的相關性分數以相同方式比對查詢,也可能出人意料。 這是因為評分公式的元件不僅僅是 TF/IDF。 在此情況下,檔 3 的分數稍高,因為其描述較短。 瞭解 Lucene 的實際評分公式 ,以瞭解字段長度和其他因素如何影響相關性分數。

某些查詢類型(通配符、前置詞、regex)一律會為整體檔分數貢獻常數分數。 這可讓透過查詢擴充找到的相符專案包含在結果中,但不會影響排名。

範例說明為何如此重要。 通配符搜尋,包括前置詞搜尋,依定義模棱兩可,因為輸入是具有非常大量不同字詞之潛在相符專案的部分字串(請考慮 “tour*” 的輸入,且符合「旅遊」、「導覽」和「旅遊線」上的相符專案)。 鑒於這些結果的性質,無法合理推斷哪些詞彙比其他字詞更有價值。 基於這個理由,我們會忽略評分結果查詢通配符、前置詞和 regex 類型的詞彙頻率。 在包含部分和完整字詞的多部分搜尋要求中,部分輸入的結果會與常數分數併入,以避免對潛在非預期相符項目產生偏差。

相關性微調

在 Azure AI 搜尋服務中,有兩種方式可調整相關性分數:

  1. 評分配置檔 會根據一組規則,將結果排名清單中的檔升階。 在我們的範例中,我們可以考慮在標題字段中比描述欄位中相符的檔更相關的檔。 此外,如果我們的指數有每個酒店的價格欄位,我們可以推廣價格較低的檔。 深入瞭解如何將 評分配置檔新增至搜尋索引

  2. 詞彙提升 (僅適用於 Full Lucene 查詢語法中),可提供可套用至查詢樹狀結構任何部分的提升運算符 ^ 。 在我們的範例中,您可以搜尋確切字詞的空調條件或前置詞,而不是搜尋前置詞,而是藉由將提升套用至字詞查詢來排名較高的檔:air-condition^2||空調*。 深入了解 查詢中的字詞提升。

分散式索引中的評分

Azure AI 搜尋中的所有索引都會自動分割成多個分區,讓我們在服務相應增加或相應減少期間,快速將索引分散到多個節點。 發出搜尋要求時,會針對每個分區個別發出。 接著會合併每個分區的結果,並依分數排序(如果未定義其他順序)。 請務必知道評分函式會根據分區內所有檔中的反向文件頻率來加權查詢字詞頻率,而不是在所有分區中!

這表示,如果相同檔位於不同的分區上,則相關性分數 可能會 有所不同。 幸運的是,這類差異通常會隨著索引中的檔數目增加而消失,因為更均勻的字詞分佈。 您無法假設將放置任何指定檔的分區。 不過,假設檔索引鍵不會變更,它一律會指派給相同的分區。

一般而言,如果順序穩定性很重要,檔分數並不是排序檔的最佳屬性。 例如,假設有兩份具有相同分數的檔,則不保證一個檔會在後續的相同查詢執行中出現。 檔分數應該只提供與結果集中其他文件相關的一般文件相關性。

推論

商業搜尋引擎的成功提高了對私人數據全文搜索的期望。 對於幾乎任何類型的搜尋體驗,我們現在期望引擎瞭解我們的意圖,即使字詞拼錯或不完整。 我們甚至可以根據我們從未指定的接近對等詞彙或同義字來預期相符專案。

從技術觀點來看,全文搜索非常複雜,需要複雜的語言分析和系統化方法來處理,以擷取、擴充和轉換查詢詞彙來提供相關結果。 鑒於固有的複雜性,有許多因素可能會影響查詢的結果。 因此,投資時間瞭解全文搜索的機制,在嘗試處理非預期的結果時,提供有形的好處。

本文探索了 Azure AI 搜尋內容中的全文搜索。 我們希望它提供您足夠的背景,以辨識解決常見查詢問題的潛在原因和解決方法。

下一步

另請參閱

搜尋文件 REST API

簡單查詢語法

完整的 Lucene 查詢語法

處理搜尋結果