查询字符串查询
一个 query_string
查询基于 查询字符串语法 解析查询字符串。它提供了一种创建功能强大但简洁的查询方式,可以包含通配符并搜索多个字段。
使用 query_string
查询不会返回嵌套文档。要搜索嵌套字段,请使用 nested
查询。
查询字符串查询具有严格的语法,如果语法无效会返回错误。因此,它不适用于搜索框应用程序。对于不那么严格的替代方案,请考虑使用 simple_query_string
查询。如果您不需要查询语法支持,请使用 match
查询。
查询字符串语法
查询字符串语法基于 Apache Lucene 查询语法。
您可以在以下情况下使用查询字符串语法
- 在
query_string
查询中,例如GET _search { "query": { "query_string": { "query": "the wind AND (rises OR rising)" } } }
- 在 OpenSearch Dashboards 的 Discover 或 Dashboard 应用程序中,如果您关闭 DQL,如下图所示。
DQL 和查询字符串查询(Lucene)语言是 Discover 和 Dashboards 中搜索栏的两种语言选项。要比较这些语言选项,请参阅 Discover 和 Dashboard 搜索栏。
- 如果您使用 HTTP 请求查询参数进行搜索,例如
GET _search?q=wind
查询字符串由术语和运算符组成。术语是单个单词(例如,在查询 wind rises
中,术语是 wind
和 rises
)。如果多个术语用引号括起来,它们将被视为一个短语,其中单词按出现的顺序匹配(例如,"wind rises"
)。运算符(例如 OR
、AND
和 NOT
)指定用于解释查询字符串中文本的布尔逻辑。
本节中的示例使用包含以下映射和文档的索引
PUT /testindex
{
"mappings": {
"properties": {
"title": {
"type": "text",
"fields": {
"english": {
"type": "text",
"analyzer": "english"
}
}
}
}
}
}
PUT /testindex/_doc/1
{
"title": "The wind rises"
}
PUT /testindex/_doc/2
{
"title": "Gone with the wind",
"description": "A 1939 American epic historical film"
}
PUT /testindex/_doc/3
{
"title": "Windy city"
}
PUT /testindex/_doc/4
{
"article title": "Wind turbines"
}
保留字符
以下是查询字符串查询的保留字符列表
+
, -
, =
, &&
, ||
, >
, <
, !
, (
, )
,{
, }
, [
, ]
, ^
, "
, ~
, *
, ?
, :
, \
, /
使用反斜杠 (\
) 转义保留字符。发送 JSON 请求时,请使用双反斜杠 (\\
) 转义保留字符(因为反斜杠字符本身是保留字符,您必须用另一个反斜杠转义反斜杠)。
例如,要搜索表达式 2*3
,请指定查询字符串:2\\*3
GET /testindex/_search
{
"query": {
"query_string": {
"query": "title: 2\\*3"
}
}
}
>
和 <
符号无法转义。它们被解释为范围查询。
空白字符和空查询
空白字符不被视为运算符。如果查询字符串为空或只包含空白字符,则查询不会返回结果。
字段名
在冒号前指定字段名称。下表包含带字段名称的查询示例。
在 query_string 查询中的查询 | 在 Discover 中的查询 | 文档匹配条件 | 来自 testindex 索引的匹配文档 |
---|---|---|---|
title: wind | title: wind | title 字段包含单词 wind 。 | 1, 2 |
title: (wind OR windy) | title: (wind OR windy) | title 字段包含单词 wind 或单词 windy 。 | 1, 2, 3 |
title: \"wind rises\" | title: "wind rises" | title 字段包含短语 wind rises 。用反斜杠转义引号。 | 1 |
article\\ title: wind | article\ title: wind | article title 字段包含单词 wind 。用反斜杠转义空格字符。 | 4 |
title.\\*: rise | title.\*: rise | 每个以 title. 开头的字段(在此示例中为 title.english )包含单词 rise 。用反斜杠转义通配符。 | 1 |
_exists_: description | _exists_: description | 字段 description 存在。 | 2 |
通配符表达式
您可以使用特殊字符指定通配符表达式:?
替换单个字符,*
替换零个或多个字符。
示例
以下查询搜索标题中包含单词 gone
且描述中包含以 hist
开头的单词的文档
GET /testindex/_search
{
"query": {
"query_string": {
"query": "title: gone AND description: hist*"
}
}
}
通配符查询可能会占用大量内存,从而降低性能。单词开头的通配符(例如,*cal
)开销最大,因为匹配此类通配符的文档需要检查索引中的所有术语。要禁用前导通配符,请将 allow_leading_wildcard
设置为 false
。
为了提高效率,纯通配符(例如 *
)被重写为 exists
查询。因此,description: *
通配符将匹配 description
字段中包含空值的文档,但不会匹配 description
字段缺失或具有 null
值的文档。
如果将 analyze_wildcard
设置为 true
,OpenSearch 将分析以 *
结尾的查询(例如 hist*
)。因此,OpenSearch 将通过对前 n-1 个词元进行精确匹配和对最后一个词元进行前缀匹配来构建一个包含结果词元的布尔查询。
正则表达式
要在查询字符串中指定正则表达式模式,请用正斜杠 (/
) 将它们括起来,例如 title: /w[a-z]nd/
。
allow_leading_wildcard
参数不适用于正则表达式。例如,诸如 /.*d/
的查询字符串将检查索引中的所有术语。
模糊查询
您可以使用 ~
运算符运行模糊查询,例如 title: rise~
。
该查询搜索包含与搜索词在最大允许编辑距离内相似的术语的文档。编辑距离定义为 Damerau-Levenshtein 距离,它衡量将一个术语更改为另一个术语所需的一个字符更改(插入、删除、替换或转置)的数量。
默认编辑距离为 2 应能捕获 80% 的拼写错误。要更改默认编辑距离,请在 ~
运算符后指定新的编辑距离。例如,要将编辑距离设置为 1
,请使用查询 title: rise~1
。
不要混合使用模糊和通配符运算符。如果同时指定模糊和通配符运算符,其中一个运算符将不被应用。例如,如果您搜索 wnid*~1
,通配符运算符 *
将被应用,但模糊运算符 ~1
将不被应用。
邻近查询
邻近查询不要求搜索短语按指定顺序排列。它允许短语中的单词以不同的顺序出现或被其他单词分隔。邻近查询指定短语中单词的最大编辑距离。例如,以下查询在匹配指定短语中的单词时允许编辑距离为 4:
GET /testindex/_search
{
"query": {
"query_string": {
"query": "title: \"wind gone\"~4"
}
}
}
当 OpenSearch 匹配文档时,文档中单词与查询中指定单词顺序越接近(编辑距离越小),文档的相关性得分就越高。
范围
要为数值、字符串或日期字段指定范围,请使用方括号 ([min TO max]
) 表示包含范围,使用花括号 ({min TO max}
) 表示排除范围。您还可以混合使用方括号和花括号来包含或排除下限和上限(例如,{min TO max]
)。
日期范围的日期必须以您在映射包含日期的字段时使用的格式提供。有关支持的日期格式的更多信息,请参阅 格式。
下表提供了范围语法示例。
数据类型 | 查询 | 查询字符串 |
---|---|---|
数值 | 帐号在 1 到 15 之间(包含 1 和 15)的文档。 | account_number: [1 TO 15] 或account_number: (>=1 AND <=15) 或account_number: (+>=1 +<=15) |
帐号为 15 或更大的文档。 | account_number: [15 TO *] 或account_number: >=15 (注意 >= 符号后没有空格) | |
字符串 | 姓氏从 Bates(包含)到 Duke(不包含)的文档。 | lastname: [Bates TO Duke} 或lastname: (>=Bates AND <Duke) |
姓氏按字母顺序在 Bates 之前的文档。 | lastname: {* TO Bates} 或lastname: <Bates (注意在 < 符号后没有空格) | |
日期 | 发布日期在 2023 年 3 月 21 日至 2023 年 9 月 25 日(含)之间的文档。 | release_date: [03/21/2023 TO 09/25/2023] |
作为在查询字符串中指定范围的替代方案,您可以使用范围查询,它提供了更可靠的语法。
提升
使用插入符号(^
)提升运算符来按乘数提升文档的相关性分数。 [0, 1) 范围内的值会降低相关性,大于 1 的值会提高相关性。 默认值为 1
。
下表提供了提升示例。
类型 | 描述 | 查询字符串 |
---|---|---|
单词提升 | 查找所有包含单词 street 的地址,并提升包含单词 Madison 的地址。 | address: Madison^2 street |
短语提升 | 查找标题中包含短语 wind rises 的文档,并将其提升 2 倍。 | title: \"wind rises\"^2 |
查找标题中包含单词 wind rises 的文档,并将包含短语 wind rises 的文档提升 2 倍。 | title: (wind rises)^2 |
布尔运算符
当您在查询中提供搜索词时,默认情况下,查询会返回包含至少一个所提供词的文档。 您可以使用 default_operator
参数为所有词指定一个运算符。 因此,如果您将 default_operator
设置为 AND
,则所有词都将是必需的;如果您将其设置为 OR
,则所有词都将是可选的。
+
和 -
运算符
如果您希望对必需词和可选词进行更精细的控制,可以使用 +
和 -
运算符。 +
运算符使其后的词成为必需词,而 -
运算符则排除其后的词。
例如,在查询字符串 title: (gone +wind -turbines)
中,指定词 gone
是可选的,词 wind
必须存在,并且词 turbines
必须不存在于匹配文档的标题中。
GET /testindex/_search
{
"query": {
"query_string": {
"query": "title: (gone +wind -turbines)"
}
}
}
该查询返回两个匹配文档。
{
"_index": "testindex",
"_id": "2",
"_score": 1.3159468,
"_source": {
"title": "Gone with the wind",
"description": "A 1939 American epic historical film"
}
},
{
"_index": "testindex",
"_id": "1",
"_score": 0.3438858,
"_source": {
"title": "The wind rises"
}
}
前面的查询等同于以下布尔查询:
GET testindex/_search
{
"query": {
"bool": {
"must": {
"match": {
"title": "wind"
}
},
"should": {
"match": {
"title": "gone"
}
},
"must_not": {
"match": {
"title": "turbines"
}
}
}
}
}
常规布尔运算符
或者,您可以使用以下布尔运算符:AND
、&&
、OR
、||
、NOT
、!
。 但是,这些运算符不遵循优先级规则,因此在使用多个布尔运算符时必须使用括号来指定优先级。 例如,查询字符串 title: (gone +wind -turbines)
可以使用布尔运算符重写如下:
title: ((gone AND wind) OR wind) AND NOT turbines
运行包含重写查询字符串的以下查询:
GET testindex/_search
{
"query": {
"query_string": {
"query": "title: ((gone AND wind) OR wind) AND NOT turbines"
}
}
}
该查询返回与使用 +
和 -
运算符的查询相同的结果。 但是请注意,匹配文档的相关性分数与之前的结果不同。
{
"_index": "testindex",
"_id": "2",
"_score": 1.6166971,
"_source": {
"title": "Gone with the wind",
"description": "A 1939 American epic historical film"
}
},
{
"_index": "testindex",
"_id": "1",
"_score": 0.3438858,
"_source": {
"title": "The wind rises"
}
}
分组
使用括号将多个子句或术语分组为子查询。 例如,以下查询搜索标题中必须包含单词 wind
的文档,这些文档包含单词 gone
或 rises
。
GET testindex/_search
{
"query": {
"query_string": {
"query": "title: (gone OR rises) AND wind"
}
}
}
结果包含两个匹配文档。
{
"_index": "testindex",
"_id": "1",
"_score": 1.5046883,
"_source": {
"title": "The wind rises"
}
},
{
"_index": "testindex",
"_id": "2",
"_score": 1.3159468,
"_source": {
"title": "Gone with the wind",
"description": "A 1939 American epic historical film"
}
}
您还可以使用分组来提升子查询结果或定位指定的字段,例如 title:(gone AND wind) description:(historical film)^2
。
搜索多个字段
要搜索多个字段,请使用 fields
参数。 当您提供 fields
参数时,查询会重写为 field_1: query OR field_2: query ...
。
例如,以下查询在 title
和 description
字段中搜索词 wind
或 film
:
GET testindex/_search
{
"query": {
"query_string": {
"fields": [ "title", "description" ],
"query": "wind AND film"
}
}
}
前面的查询等同于以下不提供 fields
参数的查询:
GET testindex/_search
{
"query": {
"query_string": {
"query": "(title:wind OR description:wind) AND (title:film OR description:film)"
}
}
}
搜索字段的多个子字段
要搜索字段的所有内部字段,您可以使用通配符。 例如,要搜索 address
字段中的所有子字段,请使用以下查询:
GET /testindex/_search
{
"query": {
"query_string" : {
"fields" : ["address.*"],
"query" : "New AND (York OR Jersey)"
}
}
}
前面的查询等同于以下不提供 fields
参数的查询(请注意,*
使用 \\
进行转义):
GET /testindex/_search
{
"query": {
"query_string" : {
"query" : "address.\\*: New AND (York OR Jersey)"
}
}
}
提升
从每个搜索词生成的子查询使用 dis_max
查询与 tie_breaker
结合。 要提升单个字段,请使用 ^
运算符。 例如,以下查询将 title
字段提升 2 倍:
GET testindex/_search
{
"query": {
"query_string": {
"fields": [ "title^2", "description" ],
"query": "wind AND film"
}
}
}
要提升字段的所有子字段,请在通配符后指定提升运算符。
GET /testindex/_search
{
"query": {
"query_string" : {
"fields" : ["work_address", "address.*^2"],
"query" : "New AND (York OR Jersey)"
}
}
}
多字段搜索参数
搜索多个字段时,您可以将额外的可选参数 type
传递给 query_string
查询。
参数 | 数据类型 | 描述 |
---|---|---|
type | 字符串 | 确定 OpenSearch 如何执行查询并对结果评分。 有效值包括 best_fields 、bool_prefix 、most_fields 、cross_fields 、phrase 和 phrase_prefix 。 默认值为 best_fields 。 有关有效值的描述,请参见多匹配查询类型。 |
query_string
查询中的同义词
query_string
查询支持使用 synonym_graph
词元过滤器进行多词同义词扩展。 如果您使用 synonym_graph
词元过滤器,OpenSearch 会为每个同义词创建一个匹配短语查询。
auto_generate_synonyms_phrase_query
参数指定是否为多词同义词自动创建匹配短语查询。 默认情况下,auto_generate_synonyms_phrase_query
为 true
,因此如果您将 ml, machine learning
指定为同义词并搜索 ml
,OpenSearch 会搜索 ml OR "machine learning"
。
或者,您可以使用连词匹配多词同义词。 如果您将 auto_generate_synonyms_phrase_query
设置为 false
,OpenSearch 会搜索 ml OR (machine AND learning)
。
例如,以下查询搜索文本 ml models
,并指定不为每个同义词自动生成匹配短语查询:
GET /testindex/_search
{
"query": {
"query_string": {
"default_field": "title",
"query": "ml models",
"auto_generate_synonyms_phrase_query": false
}
}
}
对于此查询,OpenSearch 会创建以下布尔查询:(ml OR (machine AND learning)) models
。
最小匹配度
query_string
查询围绕每个运算符拆分查询,并为整个输入创建一个布尔查询。 minimum_should_match
参数指定文档必须匹配的最小词数才能在搜索结果中返回。 例如,以下查询指定 description
字段必须为每个搜索结果匹配至少两个词:
GET /testindex/_search
{
"query": {
"query_string": {
"fields": [
"description"
],
"query": "historical epic film",
"minimum_should_match": 2
}
}
}
对于此查询,OpenSearch 会创建以下布尔查询:(description:historical description:epic description:film)~2
。
多字段的最小匹配数
如果您在 query_string
查询中指定多个字段,OpenSearch 会为指定字段创建一个 dis_max
查询。 如果您没有明确为查询词指定运算符,则整个查询文本将被视为一个子句。 OpenSearch 使用此单个子句为每个字段构建查询。 最终的布尔查询包含一个与所有字段的 dis_max
查询对应的子句,因此 minimum_should_match
参数不适用。
例如,在以下查询中,historical epic heroic
被视为单个子句:
GET /testindex/_search
{
"query": {
"query_string": {
"fields": [
"title",
"description"
],
"query": "historical epic heroic",
"minimum_should_match": 2
}
}
}
对于此查询,OpenSearch 会创建以下布尔查询:((title:historical title:epic title:heroic) | (description:historical description:epic description:heroic))
。
如果您为查询词添加显式运算符(AND
或 OR
),则每个词都被视为一个单独的子句,可以对其应用 minimum_should_match
参数。 例如,在以下查询中,historical
、epic
和 heroic
被视为单独的子句:
GET /testindex/_search
{
"query": {
"query_string": {
"fields": [
"title",
"description"
],
"query": "historical OR epic OR heroic",
"minimum_should_match": 2
}
}
}
对于此查询,OpenSearch 会创建以下布尔查询:((title:historical | description:historical) (description:epic | title:epic) (description:heroic | title:heroic))~2
。 该查询匹配三个子句中的至少两个。 每个子句表示对 title
和 description
字段上每个词的 dis_max
查询。
或者,为确保可以应用 minimum_should_match
,您可以将 type
参数设置为 cross_fields
。 这表示在分析输入文本时,具有相同分析器的字段应分组在一起:
GET /testindex/_search
{
"query": {
"query_string": {
"fields": [
"title",
"description"
],
"query": "historical epic heroic",
"type": "cross_fields",
"minimum_should_match": 2
}
}
}
对于此查询,OpenSearch 会创建以下布尔查询:((title:historical | description:historical) (description:epic | title:epic) (description:heroic | title:heroic))~2
。
但是,如果您使用不同的分析器,则必须在查询中使用显式运算符,以确保将 minimum_should_match
参数应用于每个词。
参数
下表列出了 query_string
查询支持的参数。 除 query
外,所有参数均为可选。
参数 | 数据类型 | 描述 |
---|---|---|
query | 字符串 | 可能包含查询字符串语法中的表达式以用于搜索的文本。 必需。 |
allow_leading_wildcard | 布尔型 | 指定 * 和 ? 是否允许作为搜索词的第一个字符。 默认值为 true 。 |
analyze_wildcard | 布尔型 | 指定 OpenSearch 是否应尝试分析通配符词。 默认值为 false 。 |
分析器 | 字符串 | 用于将查询字符串文本分词的分析器。 默认值是为 default_field 指定的索引时间分析器。 如果未为 default_field 指定分析器,则 analyzer 是索引的默认分析器。 有关 index.query.default_field 的更多信息,请参见动态索引级别索引设置。 |
auto_generate_synonyms_phrase_query | 布尔型 | 指定是否为多词同义词自动创建匹配短语查询。 例如,如果您将 ba, batting average 指定为同义词并搜索 ba ,OpenSearch 会搜索 ba OR "batting average" (如果此选项为 true )或 ba OR (batting AND average) (如果此选项为 false )。 默认值为 true 。 |
提升 | 浮点数 | 按给定乘数提升子句。在复合查询中,用于衡量子句的权重。值在 [0, 1) 范围内会降低相关性,大于 1 的值会增加相关性。默认值为 1 。 |
default_field | 字符串 | 如果查询字符串中未指定字段,则在其中搜索的字段。 支持通配符。 默认为 index.query. Default_field 索引设置中指定的值。 默认情况下,index.query. Default_field 为 * ,这意味着提取所有符合词查询条件的字段并过滤元数据字段。 如果未指定 prefix ,则将提取的字段组合成一个查询。 符合条件的字段不包括嵌套文档。 搜索所有符合条件的字段可能是一项资源密集型操作。 indices.query.bool.max_clause_count 搜索设置定义了可一次查询的字段数和词数乘积的最大值。 indices.query.bool.max_clause_count 的默认值为 1,024。 |
default_operator | 字符串 | 如果查询字符串包含多个搜索词,则文档要被视为匹配,是需要所有词都匹配(AND )还是只需要一个词匹配(OR )。 有效值为- OR :字符串 to be 被解释为 to OR be - AND :字符串 to be 被解释为 to AND be 默认值为 OR 。 |
enable_position_increments | 布尔型 | 当为 true 时,结果查询会识别位置增量。 当删除停用词在词之间留下不必要的“间隙”时,此设置很有用。 默认值为 true 。 |
fields | 字符串数组 | 要搜索的字段列表(例如,"fields": ["title^4", "description"] )。 支持通配符。 如果未指定,则默认为 index.query. Default_field 设置,该设置默认为 ["*"] 。 |
fuzziness | 字符串 | 确定词是否匹配某个值时,将一个单词更改为另一个单词所需的字符编辑(插入、删除、替换)次数。 例如,wined 和 wind 之间的距离为 1。 有效值为非负整数或 AUTO 。 默认值 AUTO 会根据每个词的长度选择一个值,对于大多数用例来说是一个不错的选择。 |
fuzzy_max_expansions | 正整数 | 查询可以扩展到的最大词数。 模糊查询“扩展到” fuzziness 中指定距离内的多个匹配词。 然后 OpenSearch 会尝试匹配这些词。 默认值为 50 。 |
fuzzy_transpositions | 布尔型 | 将 fuzzy_transpositions 设置为 true (默认值)会在 fuzziness 选项的插入、删除和替换操作中添加相邻字符的交换。 例如,如果 fuzzy_transpositions 为 true(交换“n”和“i”),则 wind 和 wnid 之间的距离为 1;如果为 false(删除“n”,插入“n”),则距离为 2。 如果 fuzzy_transpositions 为 false,则 rewind 和 wnid 与 wind 的距离相同(2),尽管以人为中心来看 wnid 是一个明显的拼写错误。 默认值是大多数用例的不错选择。 |
lenient | 布尔型 | 将 lenient 设置为 true 会忽略查询与文档字段之间的数据类型不匹配。 例如,查询字符串 "8.2" 可以匹配 float 类型的字段。 默认值为 false 。 |
最大确定化状态 (max_determinized_states) | 正整数 | Lucene 可以为包含正则表达式(例如 "query": "/wind.+?/" )的查询字符串创建的“状态”数(衡量复杂性)的最大值。 更大的数字允许使用更多内存的查询。 默认值为 10,000。 |
minimum_should_match | 正或负整数,正或负百分比,组合 | 如果查询字符串包含多个搜索词并且您使用 or 运算符,则文档要被视为匹配所需的词数。 例如,如果 minimum_should_match 为 2,则 wind often rising 不匹配 The Wind Rises. 。 如果 minimum_should_match 为 1 ,则匹配。 有关详细信息,请参见最小匹配数。 |
phrase_slop | 整数 | 匹配词之间允许的最大单词数。 如果 phrase_slop 为 2,则短语中匹配词之间最多允许有两个单词。 转置的单词的错位量为 2。 默认值为 0 (精确短语匹配,其中匹配的单词必须相邻)。 |
quote_analyzer | 字符串 | 用于将查询字符串中的引用文本分词的分析器。 对于引用文本,它会覆盖 analyzer 参数。 默认值为为 default_field 指定的 search_quote_analyzer 。 |
quote_field_suffix | 字符串 | 此选项支持使用与非精确匹配不同的分析方法来搜索精确匹配(用引号括起来)。 例如,如果 quote_field_suffix 为 .exact 并且您在 title 字段中搜索 \"lightly\" ,OpenSearch 会在 title.exact 字段中搜索单词 lightly 。 这个第二个字段可能会使用不同的类型(例如,keyword 而不是 text )或不同的分析器。 |
重写 (rewrite) | 字符串 | 确定 OpenSearch 如何重写和评分多词查询。 有效值包括 constant_score 、scoring_boolean 、constant_score_boolean 、top_terms_N 、top_terms_boost_N 和 top_terms_blended_freqs_N 。 默认值为 constant_score 。 |
time_zone | 字符串 | 指定所需时区与 UTC 的小时偏移量。 如果查询字符串包含日期范围,则需要指示时区偏移量。 例如,对于包含日期范围的查询(例如 "query": "wind rises release_date[2012-01-01 TO 2014-01-01]" ),请设置 time_zone": "-08:00" )。 用于指定偏移小时数的默认时区格式为 UTC 。 |
查询字符串查询可能会在内部转换为前缀查询。 如果search.allow_expensive_queries
设置为 false
,则不执行前缀查询。 如果启用了 index_prefixes
,则会忽略 search.allow_expensive_queries
设置,并构建和执行优化查询。