字符串查询

字符串查询 #

一个 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)"
     }
   }
 }

如果你使用 HTTP 请求查询参数进行搜索,例如:

 GET _search?q=wind

字符串查询由词项和运算符组成。词项是一个单词(例如,在查询 wind rises 中,词项是 windrises )。如果多个词项被引号包围,它们被视为一个短语,其中单词按出现的顺序匹配(例如, “wind rises” )。运算符(如 ORANDNOT )指定用于解释查询字符串中文本的布尔逻辑。

本节中的示例使用一个包含以下映射和文档的索引:

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 查询中的查询文档匹配的标准从 testindex 索引中匹配文档
title: windtitle 字段包含单词 wind 。1、2
title: (wind OR windy)title 字段包含单词 wind 或单词 windy 。1、2、3
title: \"wind rises\"title 字段包含短语 wind rises 。使用反斜杠转义引号。1
article\\ title: windarticle title 字段包含单词 wind 。用反斜杠转义空格字符。4
title.\\*: rise以 title. 开头的每个字段(在这个例子中是 title.english )都包含单词 rise 。用反斜杠转义通配符。1
_exists_: descriptionThe field description exists. 字段 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 ,Easysearch 将分析以 * 结尾的查询(例如 hist* )。因此,Easysearch 将通过在第一个 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"
    }
  }
}

当 Easysearch 匹配文档时,文档中的词语与查询中指定的词语顺序越接近(即编辑距离越小),该文档的相关性得分就越高。

范围查询 #

要为数值、字符串或日期字段指定范围,请使用方括号( [min TO max] )表示包含范围,使用花括号( {min TO max} )表示排除范围。您也可以混合使用方括号和花括号来包含或排除下限和上限(例如, {min TO max] )。

日期范围必须使用您在映射包含日期的字段时使用的格式提供。有关支持的日期格式的更多信息,请参阅格式。

下表提供了范围语法示例。

数据类型查询内容字符串查询
Numeric账户号码在 1 到 15(含)范围内的文档。account_number: [1 TO 15]account_number: (>=1 AND <=15)account_number: (+>=1 +<=15)
账户号码为 15 及以上的文档。account_number: [15 TO *]account_number: >=15 (注意 >= 符号后没有空格)
String姓氏从 Bates(包含)到 Duke(不包含)的文档。[Bates TO Duke}lastname: (>=Bates AND <Duke)
文档中姓氏在字母顺序上位于 Bates 之前。lastname: { * TO Bates} 或 lastname: <Bates (注意 < 符号后没有空格)
Date发布日期在 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) 可以使用布尔运算符重写如下:

运行以下包含重写查询字符串的查询:

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"
  }
}

分组 #

使用括号将多个子句或词项组合为子查询。例如,以下查询搜索包含 gonerises 的文档,这些文档必须在标题中包含 wind

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 ...

例如,以下查询会在 titledescription 字段中搜索 windfilm

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 查询。

参数数据类型描述
typeString确定 Easysearch 如何执行查询和评分结果。有效值为 best_fields 、 bool_prefix 、 most_fields 、 cross_fields 、 phrase 和 phrase_prefix 。默认值为 best_fields 。有关有效值的说明,请参阅多值查询类型。

query_string 查询中的同义词 #

query_string 查询支持使用 synonym_graph 令牌过滤器进行多词同义词扩展。如果你使用 synonym_graph 令牌过滤器,Easysearch 会为每个同义词创建一个匹配短语查询。

auto_generate_synonyms_phrase_query 参数指定是否为多词同义词自动创建匹配短语查询。默认情况下, auto_generate_synonyms_phrase_query 为 true ,因此如果你指定 ml, machine learning 为同义词并搜索 ml ,Easysearch 会搜索 ml OR "machine learning"

或者,您可以使用连词来匹配多词同义词。如果您将 auto_generate_synonyms_phrase_query 设置为 false ,Easysearch 将搜索 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
    }
  }
}

对于此查询,Easysearch 创建以下布尔查询: (ml OR (machine AND learning)) models

Minimum should match 最小匹配 #

query_string 查询会在每个运算符周围分割查询,并为整个输入创建一个布尔查询。 minimum_should_match 参数指定文档必须匹配的最小词数才能在搜索结果中返回。例如,以下查询指定 description 字段必须至少匹配两个词才能为每个搜索结果返回:

GET /testindex/_search
{
  "query": {
    "query_string": {
      "fields": [
        "description"
      ],
      "query": "historical epic film",
      "minimum_should_match": 2
    }
  }
}

对于此查询,Easysearch 创建以下布尔查询: (description:historical description:epic description:film)~2

最小值应与多个字段匹配 #

如果你在 query_string 查询中指定了多个字段,Easysearch 会为指定的字段创建 dis_max 查询。如果你没有显式指定查询项的操作符,整个查询文本被视为一个子句。Easysearch 使用这个单一子句为每个字段构建查询。最终的布尔查询包含一个对应于所有字段 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
    }
  }
}

对于此查询,Easysearch 创建以下布尔查询: ((title:historical title:epic title:heroic) | (description:historical description:epic description:heroic))

如果你在查询词中添加显式操作符( ANDOR ),每个词被视为一个独立的子句,可以应用 minimum_should_match 参数。例如,在以下查询中, historicalepicheroic 被视为独立的子句:

GET /testindex/_search
{
  "query": {
    "query_string": {
      "fields": [
        "title",
        "description"
      ],
      "query": "historical OR epic OR heroic",
      "minimum_should_match": 2
    }
  }
}

对于此查询,Easysearch 创建以下布尔查询: ((title:historical | description:historical) (description:epic | title:epic) (description:heroic | title:heroic))~2 。该查询匹配至少三个子句中的两个。每个子句都表示在每个词项的 titledescription 字段上的 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
    }
  }
}

对于此查询,Easysearch 创建以下布尔查询: ((title:historical | description:historical) (description:epic | title:epic) (description:heroic | title:heroic))~2

然而,如果你使用不同的分词器,必须在查询中使用显式操作符,以确保 minimum_should_match 参数应用于每个词。

参数说明 #

下表列出了 query_string 查询支持的参数。除 query 外,所有参数都是可选的。

参数数据类型描述
queryString用于搜索的查询字符串语法中可能包含的表达式。必填。
allow_leading_wildcardBoolean指定是否允许 * 和 ? 作为搜索词的首字符。默认为 true 。
analyze_wildcardBoolean指定 Easysearch 是否应尝试分析通配符词项。默认值为 false 。
analyzerString用于对查询字符串文本进行分词的分词器。默认值为为 default_field 指定的索引时分词器。如果未为 default_field 指定分词器,则 analyzer 为索引的默认分词器。有关 index.query.default_field 的更多信息,请参阅动态索引级索引设置。
auto_generate_synonyms_phrase_queryBoolean指定是否自动为多词同义词创建匹配短语查询。例如,如果你将 ba, batting average 指定为同义词并搜索 ba ,Easysearch 会搜索 ba OR “batting average” (如果此选项为 true )或 ba OR (batting AND average) (如果此选项为 false )。默认值为 true 。
boostfloat通过给定的乘数提升子句的权重。适用于在复合查询中对子句进行加权。[0, 1) 范围内的值会降低相关性,而大于 1 的值会增加相关性。默认值为 1 。
default_fieldString如果查询字符串中未指定字段,则在此字段中搜索。支持通配符。默认值为 index.query. Default_field 索引设置中指定的值。默认情况下, index.query. Default_field 是 * ,这意味着提取所有适用于 term 查询的字段并过滤元数据字段。如果未指定 prefix ,则提取的字段将组合成一个查询。符合条件的字段不包括嵌套文档。搜索所有符合条件的字段可能是一个资源密集型操作。 indices.query.bool.max_clause_count 搜索设置定义了字段数量和一次可以查询的词数乘积的最大值。 indices.query.bool.max_clause_count 的默认值为 1,024。
default_operatorString如果查询字符串包含多个搜索词,文档是否需要所有词都匹配( AND )或只需一个词匹配( OR )才被视为匹配。有效值为:- OR : 字符串 to be 被解释为 to OR be;- AND : 字符串 to be 被解释为 to AND be;默认为 OR 。
enable_position_incrementsBoolean当 true 时,生成的查询会考虑位置增量。当停用词被移除时,留下不想要的“间隙”时,此设置很有用。默认值为 true 。
fields字符串数组要搜索的字段列表(例如, “fields”: [“title^4”, “description”] )。支持通配符。如果未指定,则默认为 index.query. Default_field 设置,该设置默认为 ["*"] 。
fuzzinessString在确定词项是否与值匹配时,将一个词转换为另一个词所需的字符编辑次数(插入、删除、替换)。例如, wined 和 wind 之间的距离是 1。有效值是非负整数或 AUTO 。默认值 AUTO 根据每个词的长度选择值,对于大多数用例是一个不错的选择。
fuzzy_max_expansions正整数查询可以扩展到的最大词数。模糊查询会扩展到与指定距离( fuzziness )内的匹配词。然后 Easysearch 尝试匹配这些词。默认值为 50 。
fuzzy_transpositionsBoolean将 fuzzy_transpositions 设置为 true (默认)会在 fuzziness 选项的插入、删除和替换操作中添加相邻字符的交换。例如,如果 fuzzy_transpositions 为真(交换“n”和“i”),则 wind 和 wnid 之间的距离为 1;如果为假(删除“n”,插入“n”),则距离为 2。如果 fuzzy_transpositions 为假, rewind 和 wnid 与 wind 的距离相同(2),尽管从更以人为中心的观点来看, wnid 是一个明显的拼写错误。对于大多数用例,默认值是一个不错的选择。
lenientBoolean将 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 ,则匹配。详情请参阅 Minimum should match。
phrase_slopInteger允许在匹配的词之间出现的最大词数。如果 phrase_slop 为 2,则短语中匹配的词之间最多允许两个词。调换顺序的词有 2 的容差。默认值为 0 (精确短语匹配,其中匹配的词必须相邻)。
quote_analyzerString用于在查询字符串中分词引号内文本的分词器。覆盖引号文本的 analyzer 参数。默认值为 default_field 指定的 search_quote_analyzer 。
quote_field_suffixString此选项支持使用与非精确匹配不同的分析方法来搜索精确匹配(用引号括起来)。例如,如果 quote_field_suffix 是 .exact ,而你搜索 "lightly" 在 title 字段中,Easysearch 会在 lightly 字段中搜索单词 title.exact 。这个第二个字段可能使用不同的类型(例如, keyword 而不是 text )或不同的分词器。
rewriteString确定 Easysearch 如何重写和评分多词查询。有效值为 constant_score 、 scoring_boolean 、 constant_score_boolean 、 top_terms_N 、 top_terms_boost_N 和 top_terms_blended_freqs_N 。默认值为 constant_score 。
time_zoneString指定从 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 设置,并构建并执行优化后的查询。