Azure AI 搜索中的 Lucene 查询语法
在 Azure AI 搜索中创建查询时,可以选择用于专用查询窗体的完整 Lucene 查询分析器语法:通配符、模糊搜索、邻近搜索、正则表达式。 除了通过 $filter
表达式构造的“范围搜索”之外,大部分 Lucene 查询分析器语法都在 Azure AI 搜索中完整实现。
若要使用完整的 Lucene 语法,请将 queryType 设置为full
,并传入为通配符、模糊搜索或由完整语法支持的其他查询形式之一模式化的查询表达式。 在 REST 中,查询表达式在搜索文档 (REST API) 请求的 search
参数中提供。
示例(完整语法)
下面的示例是一个使用完整语法构造的搜索请求。 此特定示例演示了字段内搜索和字词提升。 查找类别字段中包含“budget
”这一字词的酒店。 由于字词提升值 (3),任何包含短语“"recently renovated"
”的文档排名都会更高。
POST /indexes/hotels-sample-index/docs/search?api-version=2024-07-01
{
"queryType": "full",
"search": "category:budget AND \"recently renovated\"^3",
"searchMode": "all"
}
searchMode
参数虽然不特定于任何查询类型,但在本例中却是相关的。 无论运算符何时出现在查询上,通常都应该设置 searchMode=all
以确保匹配所有条件。
有关更多示例,请参阅 Lucene 查询语法示例。 有关查询请求和参数(包括 searchMode)的详细信息,请参阅搜索文档 (REST API)。
语法基础知识
下面的语法基础适用于所有使用 Lucene 语法的查询。
上下文中的运算符评估
位置决定符号解释为运算符或者解释为字符串中的另一个字符。
例如,Lucene 完整语法中,波浪线 (~
) 用于模糊搜索和邻近搜索。 如果放在引用短语之后,~
调用邻近搜索。 如果放在字词末尾,~
调用模糊搜索。
在字词中,例如“business~analyst
”,字符不评估为运算符。 在此情况下,假设查询是字词或短语查询,则使用词法分析的全文搜索会删除 ~
并将字词“business~analyst
”分为两部分:business
或 analyst
。
上面的示例是波形符 (~
),不过相同原则也适用于每个运算符。
转义特殊字符
若要使用任何搜索运算符作为搜索文本的一部分,请使用一个反斜杠 (\
) 作为前缀对该字符进行转义。 例如,若要执行对 https://
的通配符搜索(其中 ://
是查询字符串的一部分),需要指定 search=https\:\/\/*
。 同样,转义的电话号码模式可能类似于 \+1 \(800\) 642\-7676
。
需要转义的特殊字符包括下列项:
+ - & | ! ( ) { } [ ] ^ " ~ * ? : \ /
注意
尽管转义将标记保留在一起,但在编制索引期间,词法分析可能会将它们去除。例如,标准 Lucene 分析器会在连字符、空格和其他字符处断开单词。 如果需要在查询字符串中使用特殊字符,则可能需要使用会将它们保留在索引中的分析器。 可供选择的一些项包括 Azure 自然语言分析器(它会保留带连字符的单词)和自定义分析器(用于更复杂的模式)。 有关详细信息,请参阅部分词语、模式和特殊字符。
对 URL 中的不安全及保留字符进行编码
请确保对 URL 中的所有不安全字符和保留字符进行编码。 例如,“#
”是不安全字符,因为它是 URL 中的片段/定位标识符。 如果用于 URL,则该字符必须编码为 %23
。 由于 &
和 =
在 Azure AI 搜索中分隔参数并指定值,因而是保留字符的示例。 请参阅 RFC1738:统一资源定位器 (URL) 以获取更多详细信息。
不安全字符为 " ` < > # % { } | \ ^ ~ [ ]
。 保留字符为 ; / ? : @ = + &
。
布尔运算符
可以在查询字符串中嵌入布尔运算符以提高匹配的精准率。 除了字符运算符之外,完整语法还支持文本运算符。 始终全部以大写字母指定文本布尔运算符 (AND、OR、NOT)。
文本运算符 | 字符 | 示例 | 使用情况 |
---|---|---|---|
AND | + |
wifi AND luxury |
指定匹配项必须包含的字词。 在此示例中,查询引擎查找同时包含“wifi ”和“luxury ”的文档。 还可以在字词前面使用加号字符 (+ ),使其成为必需项。 例如,+wifi +luxury 规定两个术语必须出现在单个文档的某个字段中。 |
OR | (无)1 | wifi OR luxury |
找到任一字词就意味着找到匹配项。 在此示例中,查询引擎返回包含“wifi ”和/或“luxury ”的文档的匹配项。 由于 OR 是默认连接运算符,因此也可以省略,这样 wifi luxury 等同于 wifi OR luxury 。 |
NOT | ! 、- |
wifi -luxury |
返回不包含该字词的文档的匹配项。 例如:“wifi -luxury ”搜索包含“wifi ”字词但不包含“luxury ”的文档。 |
1 OR 操作不支持 |
字符。
NOT 布尔运算符
重要
NOT 运算符(NOT
、!
或 -
)在完整语法和简单语法中的行为不同。
- 在简单语法中,带有否定的查询始终会自动添加通配符。 例如,查询
-luxury
会自动扩展为-luxury *
。 - 在完整语法中,带有否定的查询不能与通配符结合。 例如,不允许使用查询
-luxury *
。 - 在完整语法中,不允许使用带有单个否定的查询。 例如,不允许使用查询
-luxury
。 - 在完整语法中,否定的行为将如同它们始终通过 AND 添加到查询中,无论搜索模式如何。
- 例如,完整语法中的完整语法查询
wifi -luxury
仅提取包含词wifi
的文档,然后将否定-luxury
应用于这些文档。
- 例如,完整语法中的完整语法查询
- 如果要使用否定来搜索索引中的所有文档,建议使用简单语法和
any
搜索模式。 - 如果要使用否定来搜索索引中的文档子集,建议使用完整语法或简单语法和所有搜索模式。
查询类型 | Search Mode | 示例查询 | 行为 |
---|---|---|---|
简单 | any | wifi -luxury |
返回索引中的所有文档。 具有“wifi”一词的文档或缺少“luxury”一词的文档的排名高于其他文档。 该查询扩展为 wifi OR -luxury OR * 。 |
简单 | 全部 | wifi -luxury |
仅返回索引中包含“wifi”一词且不包含“luxury”一词的文档。 该查询扩展为 wifi AND -luxury AND * 。 |
完全 | any | wifi -luxury |
仅返回索引中包含“wifi”一词的文档,然后从结果中删除包含“luxury”一词的文档。 |
完全 | 全部 | wifi -luxury |
仅返回索引中包含“wifi”一词的文档,然后从结果中删除包含“luxury”一词的文档。 |
字段化搜索
可以使用 fieldName:searchExpression
语法定义字段化搜索操作,其中的搜索表达式可以是单个词,也可以是一个短语,或者是括号中的更复杂的表达式,可以选择使用布尔运算符。 下面是部分示例:
genre:jazz NOT history
artists:("Miles Davis" "John Coltrane")
如果想要两个字符串评估为单个实体,请务必将多个字符串放置在引号内,正如这个在 artists
字段中搜索两个不同艺术家的情况一样。
fieldName:searchExpression
中指定的字段必须是 searchable
字段。 有关如何在字段定义中使用索引属性的详细信息,请参阅创建索引。
注意
使用字段化搜索表达式时,不需使用 searchFields
参数,因为每个字段化搜索表达式都有一个显式指定的字段名称。 但是,如果需要运行查询,则仍可使用 searchFields
参数,其中的某些部分局限于特定字段,其余部分可以应用到多个字段。 例如,查询 search=genre:jazz NOT history&searchFields=description
只将 jazz
匹配到 genre
字段,而它则会将 NOT history
与 description
字段匹配。 在 fieldName:searchExpression
中提供的字段名称始终优先于 searchFields
参数,这就是在此示例中我们不需在 searchFields
参数中包括 genre
的原因。
模糊搜索
模糊搜索查找字词中具有类似构造的匹配项,将一个字词最多扩展为符合距离条件(2 或更低)的 50 个字词。 有关详细信息,请参阅模糊搜索。
若要进行模糊搜索,请在单个词末尾使用“~
”波形符,另附带指定编辑距离的可选参数(0 到 2(默认)之间的值)。 例如,“blue~
”或“blue~1
”会返回“blue
”、“blues
”和“glue
”。
模糊搜索只能应用于字词,不能应用于带引号的短语,但可以在多部分名称或短语中单独将波浪号追加到每个字词。 例如,“Unviersty~ of~ Wshington~
”会匹配“University of Washington
”。
邻近搜索
邻近搜索用于搜索文档中彼此邻近的术语。 在短语末尾插入波形符“~
”,后跟创建邻近边界的字数。 例如,“"hotel airport"~5
”在文档中查找彼此相距五个单词以内的字词“hotel
”和“airport
”。
术语提升
术语提升是指相对于不包含术语的文档,提高包含提升术语的文档排名。 这不同于计分概要文件,因为计分概要文件提升某些字段,而非特定术语。
以下示例有助于解释这些差异。 假设某个字段中存在提升匹配度的计分概要文件,例如 musicstoreindex 示例中的“流派”。 术语提升可用于进一步提升高于其他术语的某些搜索词。 例如,“rock^2 electronic
”提升“流派”字段(高于搜索中其他搜索字段)中包含搜索词的文档。 另外,由于字词提升值 (2),包含搜索词“rock”的文档的排名要比包含搜索词“electronic”的要高。
若要提升字词,请使用插入符号 ^
,并且所搜索字词末尾还要附加提升系数(数字)。 还可以提升短语。 提升系数越高,字词相对于其他搜索词的相关性也越大。 默认情况下,提升系数是 1。 虽然提升系数必须是正数,但可以小于 1(例如 0.20)。
正则表达式搜索
正则表达式搜索根据在 Apache Lucene 下有效的模式找到匹配项,如 RegExp 类中所述。 在 Azure AI 搜索中,正则表达式包含在正斜杠 /
之间。
例如,若要查找包含“motel
”或“hotel
”的文档,请指定 /[mh]otel/
。 正则表达式搜索与单个词匹配。
除了 Azure AI 搜索施加的转义规则之外,还有某些工具和语言施加的额外的转义字符要求。 对于 JSON,包含正斜杠的字符串将使用反斜杠进行转义:“microsoft.com/azure/
”变成“search=/.*microsoft.com\/azure\/.*/
”,其中 search=/.* <string-placeholder>.*/
设置正则表达式,microsoft.com\/azure\/
是包含转义后的正斜杠的字符串。
正则表达式查询中的两个常见符号是 .
和 *
。 .
匹配任何一个字符,*
匹配前一个字符零次或更多次。 例如,“/be./
”匹配字词“bee
”和“bet
”,而“/be*/
”会匹配“be
”、“bee
”和“beee
”,但不会匹配“bet
”。 总之,“.*
”允许匹配任何字符系列,因此“/be.*/
”会匹配任何以“be
”开头的字词,例如“better
”。
如果正则表达式中出现语法错误,请查看特殊字符的转义规则。 还可以尝试不同的客户端来确认问题是否是特定于工具的。
通配符搜索
可将通常可识别的语法用于多个 (*
) 或单个 (?
) 字符通配符搜索。 完整的 Lucene 语法支持前缀和中缀匹配。 使用正则表达式语法进行后缀匹配。
请注意,Lucene 查询分析器支持将这些符号与单个术语一起使用,但不能与短语一起使用。
词缀类型 | 描述和示例 |
---|---|
前缀 | 术语片段出现在 * 或 ? 之前。 例如,search=alpha* 查询表达式返回“alphanumeric ”或“alphabetical ”。 简单和完整的语法都支持前缀匹配。 |
suffix | 术语片段出现在 * 或 ? 之后,使用正斜杠来分隔构造。 例如,search=/.*numeric/ 返回 alphanumeric 。 |
中辍 | 术语片段中包含 * 或 ? 。 例如,search=non*al 返回“non-numerical ”和“nonsensical ”。 |
可以将操作符合并到一个表达式中。 例如,980?2*
匹配“98072-1222
”和“98052-1234
”,其中 ?
匹配单个(所需的)字符,而 *
匹配跟在后面的任意长度的字符。
后缀匹配需要正则表达式正斜杠 /
分隔符。 通常,不能使用 *
或 ?
符号作为术语的第一个字符,而不使用 /
。 同样重要的是要注意,在正则表达式查询之外使用时,*
的行为有所不同。 在正则表达式正斜杠 /
分隔符之外,*
是通配符,可匹配任何一系列字符,就像正则表达式中的 .*
一样。 例如,search=/non.*al/
生成与 search=non*al
相同的结果集。
注意
通常,模式匹配很慢,因此你可能需要使用其他方法,例如边缘 n 元标记化,为搜索词中的字符序列创建标记。 使用 N 元语法词汇切分,索引将更大,但查询的执行速度可能更快,具体取决于模式构造和要编制索引的字符串的长度。 有关详细信息,请参阅部分字词搜索和包含特殊字符的模式。
分析器对通配符查询的效果
在查询分析期间,以前缀、后缀、通配符或正则表达式形式构建的查询将绕过词法分析,按原样传递到查询树。 仅当索引包含查询所指定的格式的字符串时,才会查找匹配项。 在大多数情况下,在索引期间需要使用可以保留字符串完整性的分析器,使部分字词和模式匹配能够成功。 有关详细信息,请参阅 Azure AI 搜索查询中的部分词条搜索。
考虑这样一种情况:可能想要搜索查询“terminal*
”返回包含“terminate
”、“termination
”和“terminates
”等字词的结果。
如果你要用 en.lucene(Lucene 英文版)分析器,它将对每个术语应用主动的词干提取。 例如,terminate
、termination
、terminates
都将被词汇切分到索引中的标记 termi
。 另一方面,根本不会分析使用通配符或模糊搜索的查询中的字词,因此不会有与“terminat*
”查询匹配的结果。
另一方面,Azure 分析器(在本例中是 en.microsoft 分析器)更高级一些,使用词形还原而不是词干提取。 这意味着所有生成的标记都应该是有效的英语单词。 例如,“terminate
”、“terminates
”和“termination
”在索引中几乎保持完整,对于严重依赖于通配符和模糊搜索的场景,这是更好的选择。
对通配符和正则表达式查询评分
Azure AI 搜索使用基于频率的评分 (TF-IDF) 进行文本查询。 但是,对于术语范围可能很广的通配符和正则表达式查询,则忽略频率因子,以防止排名偏向于比较少见的术语匹配。 通配符和正则表达式搜索对所有匹配项和正则表达式搜索进行相同处理。
特殊字符
在某些情况下,可能需要搜索特殊字符,如“❤”表情符号或“€”符号。 在此类情况下,请确保所使用的分析器不会筛选掉这些字符。标准分析器会跳过许多特殊字符,将其从索引中排除。
标记化特殊字符的分析器包括空格分析器,该分析器将由空格分隔的任何字符序列视为标记(因此,“❤
”字符串会被视为标记)。 另外,诸如 Azure 英语分析器(“en.microsoft”)之类的语言分析器会将“€”字符串视为标记。 可以测试分析器,看它为给定的查询生成什么标记。
使用 Unicode 字符时,请确保在查询 URL 中正确转义了符号(例如,对于“❤
”,将使用转义序列 %E2%9D%A4+
)。 某些 REST 客户端会自动执行此转换。
优先级(分组)
可以使用圆括号创建子查询,其包括附加说明语句中的运算符。 例如,“motel+(wifi|luxury)
”搜索包含“motel
”字词以及“wifi
”或“luxury
”(或两者)的文档。
字段分组与之类似,但将分组范围限定为单个字段。 例如,“hotelAmenities:(gym+(wifi|pool))
”为“gym
”和“wifi
”或“gym
”和“pool
”搜索字段“hotelAmenities
”。
查询大小限制
Azure AI 搜索会对查询大小和组合施加限制,因为不受限制的查询会使搜索服务不稳定。 查询大小和组成(子句数量)有限制。 前缀搜索的长度,以及正则表达式搜索和通配符搜索的复杂性也存在限制。 如果应用程序以编程方式生成搜索查询,则建议将其设计为不会生成无限大小的查询。
有关查询限制的详细信息,请参阅 API 请求限制。