部分字詞搜尋和具有特殊字元 (連字號、萬用字元、RegEx、模式) 的模式
部分字詞搜尋是指包含字詞片段的查詢,其中,您可能只有字詞開頭、中間或結尾 (有時稱為前置詞、中置詞或後置詞查詢),而不是整個字詞。 部分字詞搜尋可能包含片段的組合,通常會有屬於查詢字串一部分的特殊字元,例如連字號、破折號或斜線號。 常見的使用案例包括部分電話號碼、URL、字碼或連字號複合字。
如果索引沒有代表您要搜尋之文字片段的標記,部分字詞和特殊字元可能會有問題。 在 關鍵詞索引的語彙分析階段 (假設預設標準分析器),會捨棄特殊字元、分割複合字,並刪除空格符。 如果您要搜尋在語彙分析期間修改的文字片段,查詢會失敗,因為找不到相符項目。 例如,權杖化為 "1"
、"425"
、"703"
、"6214"
的電話號碼,如 +1 (425) 703-6214
不會顯示在 "3-62"
查詢中,因為該內容實際上不存在於索引中。
解決方案是在編制索引期間叫用分析器,保留完整的字串,如有需要包括空格和特殊字元,以便您可以在查詢字串中包含空格和字元。 擁有完整、未權杖化的字串可針對「開頭為」或「結尾為」查詢進行模式比對,您可以在其中針對語彙分析未轉換的字詞來評估您提供的模式。
如果您需要支援呼叫已分析內容和未分析內容的搜尋案例,請考慮在索引中建立兩個欄位,每個案例各一個。 一個欄位進行語彙分析。 第二個欄位會使用內容保留分析器來儲存完整字串,發出整個字串權杖以進行模式比對。
部分字詞搜尋介紹
Azure AI 搜尋服務在索引中掃描完整權杖化字詞,除非您包含萬用字元預留位置運算子 (*
和 ?
),或將查詢格式化為規則運算式,否則在部分字詞上找不到相符項目。
部分詞彙使用下列技術而指定:
規則運算式查詢可以是 Apache Lucene 下有效的任何規則運算式。
具有前置詞比 對的通配符運算符是指包含字詞開頭的一般辨識模式,後面接著
*
或?
後綴運算符,例如search=cap*
比對 “Cap'n Jack's Waterfront Inn” 或 “Highline Capital”。 簡單和完整的 Lucene 查詢語法支援前置詞比對。具有中置詞和後置詞比對的萬用字元會將
*
和?
運算子放在字詞的之中或開頭,而且需要規則運算式語法 (其中,運算式以正斜線括住)。 例如,查詢字串 (search=/.*numeric.*/
) 傳回 "alphanumeric" 和 "alphanumerical" 的結果作為後置詞和中置詞相符項目。
對於規則運算式、萬用字元及模糊搜尋,分析器不會在查詢時使用。 針對這些查詢表單,剖析器會偵測運算子和分隔符號是否存在,查詢字串會在不進行語彙分析的情況下傳遞至引擎。 針對這些查詢表單,會忽略欄位上指定的分析器。
注意
當部分查詢字串包含字元時,例如 URL 片段中的斜線號,您可能需要新增逸出字元。 在 JSON 中,正斜線號 /
會逸出後斜線號 \
。 因此,search=/.*microsoft.com\/azure\/.*/
是 URL 片段 "microsoft.com/azure/" 的語法。
解決部分/模式搜尋問題
當您需要搜尋片段或模式或特殊字元時,可以使用以較簡單權杖化規則運作的自訂分析器覆寫預設分析器,保留索引中的整個字串。
方法看起來像這樣:
- 定義第二個欄位來儲存字串的完整版本 (假設您想要在查詢時分析和非分析的文字)
- 評估並選擇各種在適當細微性層級發出權杖的分析器
- 將分析器指派給欄位
- 建立並測試索引
1 - 建立專用欄位
分析器會決定字詞在索引中的權杖化方式。 由於分析器會根據每個欄位指派,因此您可以在索引中建立欄位,針對不同的情節進行最佳化。 例如,您可以定義 "featureCode" 和 "featureCodeRegex",以支援在第一個進行一般全文搜尋,然後在第二個進行進階模式比對。 指派給每個欄位的分析器會決定每個欄位的內容在索引中的權杖化方式。
{
"name": "featureCode",
"type": "Edm.String",
"retrievable": true,
"searchable": true,
"analyzer": null
},
{
"name": "featureCodeRegex",
"type": "Edm.String",
"retrievable": true,
"searchable": true,
"analyzer": "my_custom_analyzer"
},
2 - 設定分析器
選擇產生整個字詞權杖的分析器時,下列分析器為常用的選擇:
分析器 | 行為 |
---|---|
語言分析器 | 保留複合字組或字串、母音變動和動詞形式的連字號。 如果查詢模式包含破折號,則使用語言分析器可能就已足夠。 |
keyword | 整個欄位的內容會標示為單一字詞。 |
whitespace | 僅在空白字元上分隔。 包含破折號或其他字元的字詞會被視為單一權杖。 |
自訂分析器 | (建議) 建立自訂分析器可讓您同時指定權杖化工具和權杖篩選器。 先前的分析器必須按原樣使用。 自訂分析器可讓您挑選要使用的權杖化工具和權杖篩選器。 建議的組合是裝載小寫權杖篩選器的關鍵字權杖化工具。 內建關鍵字分析器本身不會小寫任何大寫文字,這麼做可能會導致查詢失敗。 自訂分析器為您提供新增小寫權杖篩選器的機制。 |
使用 REST 用戶端,您可以新增測試分析器 REST 呼叫來檢查權杖化的輸出。
索引必須存在於搜尋服務上,但可以是空的。 假設現有的索引和包含破折號或部分字詞的欄位,您可以針對特定字詞嘗試各種分析器,以查看所發出的權杖。
首先,請檢查標準分析器,以查看字詞預設如何權杖化。
{ "text": "SVP10-NOR-00", "analyzer": "standard" }
評估回應以查看文字在索引內如何權杖化。 請注意每個字詞如何小寫、移除連字號,以及子字如何串分成個別的權杖。 只有符合這些權杖的查詢才會在結果中傳回這份文件。 包含 "10-NOR" 的查詢將會失敗。
{ "tokens": [ { "token": "svp10", "startOffset": 0, "endOffset": 5, "position": 0 }, { "token": "nor", "startOffset": 6, "endOffset": 9, "position": 1 }, { "token": "00", "startOffset": 10, "endOffset": 12, "position": 2 } ] }
現在,請修改要求以使用
whitespace
或keyword
分析器:{ "text": "SVP10-NOR-00", "analyzer": "keyword" }
這次回應是由單一權杖所組成,使用大寫,其中破折號會保留為字串的一部分。 如果您需要搜尋模式或部分字詞,例如 "10-NOR",查詢引擎現在具有尋找相符項目的基礎功能。
{ "tokens": [ { "token": "SVP10-NOR-00", "startOffset": 0, "endOffset": 12, "position": 0 } ] }
重要
請注意,在組建查詢樹狀時,查詢剖析器通常會在搜尋運算式中小寫字詞。 如果您在編製索引期間使用沒有小寫文字輸入的分析器,而且您未收到預期的結果,這可能就是原因。 解決方案是新增小寫權杖篩選器,如下方「使用自訂分析器」一節所述。
3 - 設定分析器
無論您是在評估分析器或繼續進行特定組態,都必須在欄位定義上指定分析器,而且如果您不使用內建分析器,則可能需要設定分析器。 交換分析器時,您通常需要重建索引 (卸除、重新建立及重新載入)。
使用內建分析器
內建分析器可以在欄位定義的 analyzer
屬性上依名稱指定,而索引中不需要額外進行設定。 下列範例示範如何在欄位上設定 whitespace
分析器。
如需其他情節,以及深入了解其他內建分析器,請參閱內建分析器。
{
"name": "phoneNumber",
"type": "Edm.String",
"key": false,
"retrievable": true,
"searchable": true,
"analyzer": "whitespace"
}
使用自訂分析器
如果您使用自訂分析器,請使用使用者定義的權杖化工具、權杖篩選以及可能組態設定組合,在索引中對其進行定義。 接下來,在欄位定義上引用該分析器,就像是內建分析器一樣。
當目標是整個字詞權杖化時,建議使用由關鍵字權杖化工具 和小寫權杖篩選所組成的自訂分析器。
- 關鍵字權杖化工具會為欄位的整個內容建立單一語彙基元。
- 小寫語彙基元篩選會將大寫字母轉換成小寫文字。 查詢剖析器通常會小寫任何大寫文字輸入。 小寫會使用權杖化字詞將輸入同質化。
下列範例說明提供關鍵字權杖化工具和小寫權杖篩選條件的自訂分析器。
{
"fields": [
{
"name": "accountNumber",
"analyzer":"myCustomAnalyzer",
"type": "Edm.String",
"searchable": true,
"filterable": true,
"retrievable": true,
"sortable": false,
"facetable": false
}
],
"analyzers": [
{
"@odata.type":"#Microsoft.Azure.Search.CustomAnalyzer",
"name":"myCustomAnalyzer",
"charFilters":[],
"tokenizer":"keyword_v2",
"tokenFilters":["lowercase"]
}
],
"tokenizers":[],
"charFilters": [],
"tokenFilters": []
}
注意
系統已知 keyword_v2
權杖化工具和 lowercase
權杖篩選條件,並使用其預設設定,這就是為什麼您可以依名稱加以引用,而不需要先行定義。
4 - 組建和測試
當您使用支援情節的分析器和欄位定義來定義索引後,請載入具有代表性字串的文件,以便測試部分字串查詢。
使用 REST 用戶端來查詢本文所述的部分詞彙和特殊字元。
前幾節說明該邏輯。 本節會逐步引導您在測試解決方案時應呼叫的每個 API。
搜尋文件說明如何使用萬用字元和規則運算式的簡單語法或完整的 Lucene 語法來建構查詢要求。
針對部分字詞查詢,例如查詢 "3-6214" 以尋找 "+1 (425) 703-6214" 的相符項目,您可以使用簡單的語法:
search=3-6214&queryType=simple
。針對中置詞和後置詞查詢,例如查詢 "num" 或 "numeric" 以尋找 "alphanumeric 的相符項目,請使用完整的 Lucene 語法和規則運算式:
search=/.*num.*/&queryType=full
最佳化前置詞和尾碼查詢
使用預設分析器比對前置詞和尾碼需要額外的查詢功能。 前置詞需要萬用字元搜尋,尾碼需要規則運算式搜尋。 這兩項功能都可能降低查詢效能。
下列範例會新增 EdgeNGramTokenFilter
,讓前置詞或尾碼比對更快速。 權杖會以包含字元的 2-25 個字元組合產生。 以下是從兩個到七個權杖的範例進程:MS、MSF、MSFT、MSFT/、MSFT/S、MSFT/SQ、MSFT/SQL。 EdgeNGramTokenFilter
需要 side
參數,其會決定要從中產生字串字元組合的一端。 針對前置詞查詢使用 front
和針對尾碼查詢使用 back
。
額外的權杖化會導致較大的索引。 如果您有足夠的容量來容納較大的索引,則回應時間較快的這個方法可能是最佳解決方案。
{
"fields": [
{
"name": "accountNumber_prefix",
"indexAnalyzer": "ngram_front_analyzer",
"searchAnalyzer": "keyword",
"type": "Edm.String",
"searchable": true,
"filterable": false,
"retrievable": true,
"sortable": false,
"facetable": false
},
{
"name": "accountNumber_suffix",
"indexAnalyzer": "ngram_back_analyzer",
"searchAnalyzer": "keyword",
"type": "Edm.String",
"searchable": true,
"filterable": false,
"retrievable": true,
"sortable": false,
"facetable": false
}
],
"analyzers": [
{
"@odata.type":"#Microsoft.Azure.Search.CustomAnalyzer",
"name":"ngram_front_analyzer",
"charFilters":[],
"tokenizer":"keyword_v2",
"tokenFilters":["lowercase", "front_edgeNGram"]
},
{
"@odata.type":"#Microsoft.Azure.Search.CustomAnalyzer",
"name":"ngram_back_analyzer",
"charFilters":[],
"tokenizer":"keyword_v2",
"tokenFilters":["lowercase", "back_edgeNGram"]
}
],
"tokenizers":[],
"charFilters": [],
"tokenFilters": [
{
"@odata.type":"#Microsoft.Azure.Search.EdgeNGramTokenFilterV2",
"name":"front_edgeNGram",
"minGram": 2,
"maxGram": 25,
"side": "front"
},
{
"@odata.type":"#Microsoft.Azure.Search.EdgeNGramTokenFilterV2",
"name":"back_edgeNGram",
"minGram": 2,
"maxGram": 25,
"side": "back"
}
]
}
若要搜尋開頭為 123
的帳戶號碼,我們可以使用下列查詢:
{
"search": "123",
"searchFields": "accountNumber_prefix"
}
若要搜尋結尾為 456
的帳戶號碼,我們可以使用下列查詢:
{
"search": "456",
"searchFields": "accountNumber_suffix"
}
下一步
本文說明分析器會如何同時造成查詢問題,也可以解決查詢問題。 在下一個步驟中,請進一步了解分析器對編製索引和查詢處理的影響。