查询字符串(query_string)查询

使用具有严格语法的解析器,根据提供的查询字符串返回文档。

该查询使用一种语法,根据运算符(如ANDNOT)来解析和拆分所给的查询字符串。 在返回匹配的文档之前,查询会单独分析每个拆分出的文本。

可以使用 query_string 查询创建包含通配符的复杂搜索、跨多个字段的搜索等等。 虽然该查询是通用的,但它却很严格,如果查询字符串包含任何无效语法,就会返回错误。

因为它会因为任何无效的语法而返回错误,所以我们不建议对搜索框使用 query_string 查询。

如果不需要支持查询语法,可以考虑使用 match 查询。 如果需要查询语法的特性,请使用 simple_query_string 查询,它没有那么严格。

请求示例

当执行下面的搜索时,query_string 查询将 (new york city) OR (big apple) 拆分成两个部分:new york citybig apple。 然后,在返回匹配的文档之前,content 字段的分析器单独将每个部分转换成词元(token)。 因为查询语法不使用空格作为运算符,所以 new york city按原样传递给分析器。

GET /_search
{
    "query": {
        "query_string" : {
            "query" : "(new york city) OR (big apple)",
            "default_field" : "content"
        }
    }
}

query_string的顶级参数

query
(必需的, string) 希望解析并用于搜索的查询字符串。参考查询字符串语法
default_field

(可选, string) 如果查询字符串中没有指定字段,你希望搜索的默认字段。

默认为 index.query.default_field 索引设置,其默认值为** 值提取符合条件查询的所有字段,并过滤元数据字段。 如果没有指定 prefix,则将所有提取出来的字段组合起来构建一个查询。

在所有符合要求的字段中搜索并不会包括 嵌套文档,请使用 nested查询 来搜索这些文档。

对于包含大量字段的映射,在所有符合条件的字段中进行搜索的成本可能会非常高。

一次可以查询的字段数量是有限制的。 它由 indices.query.bool.max_clause_count 搜索设置定义,默认为 1024。

allow_leading_wildcard
(可选, boolean) 如果为 true,通配符*?允许作为查询字符串的第一个字符。默认为 true
analyze_wildcard
(可选, boolean) 如果为 true,查询将尝试分析查询字符串中的通配符。默认为 false
analyzer
(可选, string) 用于将查询字符串中的文本转换为词元(token)的分析器 。 默认为字段 default_field 所映射的 索引时使用的分析器。 如果没有映射分析器,则使用索引的默认分析器。
auto_generate_synonyms_phrase_query
(可选, boolean) 如果为 true,将自动为多词项同义词创建 匹配短语(match phrase) 查询。 默认为 true。 有关示例请参考 同义词和query_string查询
boost

(可选, float) 用于降低或增加查询的相关性评分的浮点数。默认为 1.0

boost 值是相对于默认值 1.0 的。 当它在 01.0 之间时会降低相关性评分,而大于 1.0 时会增加相关性评分。

default_operator

(可选, string) 未指定运算符时,用于解释查询字符串中的文本的默认的布尔逻辑。有效值有:

OR (默认)
比如,查询字符串 capital of Hungary 被解释为 capital OR of OR Hungary
AND
比如,查询字符串 capital of Hungary 被解释为 capital AND of AND Hungary
enable_position_increments
(可选, boolean) 如果为 true,则在由query_string搜索构建的查询中启用位置增量。默认为 true
fields

(可选, array of strings) 你想搜索的字段的数组。

可以使用此参数跨多个字段进行搜索。参考搜索多个字段

fuzziness
(可选, string) 匹配时的最大编辑距离。有效值及更多信息请参考 模糊性
fuzzy_max_expansions
(可选, integer) 模糊匹配查询能扩展到的最大词项数。默认为50
fuzzy_prefix_length
(可选, integer) 模糊匹配的起始字符保持不变的字符数量。默认为 0
fuzzy_transpositions
(可选, boolean) 如果为true,模糊匹配的编辑可以包含两个相邻字符的交换(ab → ba)。默认为 true
lenient
(可选, boolean) 如果为 true,则忽略基于格式的错误,例如为 numeric 字段提供 text 值。 默认为 false
max_determinized_states

(可选, integer) 查询所需的自动机状态的最大值。默认为10000

Elasticsearch 内部使用Apache Lucene解析正则表达式。 Lucene 将每个正则表达式转换成一个包含许多确定状态的有限自动机。

可以使用此参数来防止该转换无意中消耗太多资源。你可能需要提高这个限制来运行复杂的正则表达式。

minimum_should_match
(可选, string) 要返回的文档必须匹配的最小子句数。 有效值及更多信息请参考 minimum_should_match参数。 查看minimum_should_match如何工作的示例。
quote_analyzer

(可选, string) 用于将查询字符串中的引用文本转换为词元(token)的分析器。 默认为字段 default_field 映射的 search_quote_analyzer

对于引用的文本,此参数会覆盖 analyzer 参数中指定的分析器。

phrase_slop
(可选, integer) 短语的匹配词元之间允许的最大位置数。默认为 0。 如果为 0,则要求精确的短语匹配。 颠倒顺序的词项的 slop 的值为 2
quote_field_suffix

(可选, string) 查询字符串中附加到引用文本的后缀。

可以使用此后缀来使用不同的分析方法进行精确匹配。参考 将精确搜索与词干混合

rewrite
(可选, string) 用于重写查询的方法。有效值及更多信息请参考rewrite参数
time_zone

(可选, string) 协调世界时(UTC)时差IANA时区,用于将查询字符串中的 date 值转换为 UTC。

有效值包括 ISO 8601 UTC 时差,如 +01:00-08:00,以及 IANA 时区识别名称,如 America/Los_Angeles

time_zone 参数影响 now日期计算值。 now 始终是 UTC 中的当前系统时间。 但是,time_zone 参数会对使用now日期计算舍入 计算的日期进行转换。 例如,time_zone 参数会将 now/d 的值进行转换。

注意事项

查询字符串语法

查询字符串“迷你语言”由 search API中的 查询字符串q 查询字符串参数使用。

查询字符串被解析为一系列词项(term)运算符(operator)。 词项(term)可以是一个单词(如quickbrown),也可以是一个用双引号括起来的短语(如"quick brown") - 它以相同的顺序搜索短语中的所有单词。

运算符允许你自定义搜索—可用选项如下所述。

字段名称(field names)

可以在查询语法中指定要搜索的字段,下面是几个例子:

  • status字段中包含单词active

    status:active
  • title 字段中包含单词 quickbrown

    title:(quick OR brown)
  • author 字段中包含精确匹配的短语"john smith"

    author:"John Smith"
  • first name 字段包含 Alice (注意,我们需要用反斜杠转义字段名称中的空格):

    first\ name:Alice
  • book.titlebook.contentbook.date 任意一个字段中包含单词 quickbrown (注意,我们需要用反斜杠转义字段名称中的*):

    book.\*:(quick OR brown)
  • 字段title有任何非null的值(只要存在这个字段,即使其值是空字符串):

    _exists_:title
通配符

通配符搜索可以在单个词项上运行,使用 ? 替换单个字符,使用 * 替换零个或多个字符:

qu?ck bro*

请注意,通配符查询会占用大量内存,并且性能非常差——只要想想需要查询多少个词项才能匹配查询字符串 "a* b* c*"

为了提高效率,纯通配符 \* 被重写为 exists 查询。 因此,通配符 "field:*" 将匹配具有空值的文档,如下所示:

{
  "field": ""
}

... 如果字段缺失或设置了显式的 null 值,则 匹配,如下所示:

{
  "field": null
}

允许在单词的开头使用通配符(例如"*ing")的资源消耗特别大,因为需要检查索引中的所有词项,以防它们匹配。 通过将 allow_leading_wildcard设置为 false,可以禁用前置通配符。

只有部分分析链应用在字符级别的操作上。 例如,如果分析器既执行转小写又执行词干分析(提取),那么只会应用转小写操作:对一个缺少某些字母的单词执行词干分析是错误的。

通过将 analyze_wildcard 设置为true,将分析以 * 结尾的查询,通过确保前 N-1 个词元(token)的精确匹配和最后一个词元的前缀匹配,从不同的词元中构建 bool 查询。

正则表达式

通过将正则表达式模式用斜杠("/")包裹,可以将它们嵌入到查询字符串中:

name:/joh?n(ath[oa]n)/

正则表达式语法 中解释了支持的正则表达式语法。

allow_leading_wildcard 参数对正则表达式没有任何控制。 下面这个查询字符串将强制 Elasticsearch 访问索引中的每个词项:

/.*n/

慎用!

模糊性(Fuzziness)

我们可以使用“模糊”运算符搜索与我们的搜索词项相似但又不完全相似的词项:

quikc~ brwn~ foks~

它使用 达梅劳-莱温斯坦距离 来查找最多有两个变化的所有词项,其变化包括单个字符的插入、删除或替换,或者两个相邻字符的位置调换。

默认的编辑距离2,但是编辑距离1应该足以捕捉 80% 的人类拼写错误。 它可以指定为:

quikc~1

避免混合使用模糊性和通配符

支持混合使用 模糊通配符 运算符。 混合使用时,其中一个运算符不会被应用。 例如,可以搜索app~1(模糊)或app*(通配符),但搜索app*~1时不会应用模糊运算符(~1)。

邻近搜索 (proximity searches)

虽然短语查询(例如"john smith")希望所有词项的顺序完全相同,但 邻近查询(proximity query) 允许指定的词语相距更远或顺序不同。 与 模糊查询(fuzzy query) 可以指定单词中字符的最大编辑距离相同,邻近搜索允许我们指定短语中单词的最大编辑距离:

"fox quick"~5

字段中的文本越接近查询字符串中指定的原始顺序,该文档就被认为越相关。 与上面的示例查询相比,短语 "quick fox" 被认为比 "quick brown fox" 更相关。

范围 (ranges)

可以为 date、numeric 或 string 字段指定范围。 包含范围用方括号[min TO max]表示,不包含范围用花括号{min TO max}表示。

  • 2012年内的所有天数:

    date:[2012-01-01 TO 2012-12-31]
  • 数字 1 到 5:

    count:[1 TO 5]
  • 介于 alphaomega 之间的标签,但不包含 alphaomega

    tag:{alpha TO omega}
  • 10以上的数字:

    count:[10 TO *]
  • 2012年之前的日期:

    date:{* TO 2012-01-01}

大括号和方括号可以组合使用:

  • 从 1 到 5 的数字,但不包括 5:

    count:[1 TO 5}

一侧无界的范围可以使用以下语法:

age:>10
age:>=10
age:<10
age:<=10

要使用简化的语法组合上限和下限,需要用 AND 运算符连接两个子句:

age:(>=10 AND <20)
age:(+>=10 +<20)

查询字符串中范围的解析可能很复杂并且容易出错。 使用显式的 range 查询 要可靠得多。

增强 (boosting)

使用增强(boost)运算符 ^ 使一个词项比另一个更相关。 例如,如果我们想找到所有关于 fox 的文档,但是我们对 quick fox 特别感兴趣:

quick^2 fox

默认 boost 的值为 1,但可以是任何正浮点数。 boost的值在 0 到 1 之间时会降低相关性。

boost也可用于短语或分组:

"john smith"^2   (foo bar)^4
布尔运算符 (boolean operators)

默认情况下,所有词项都是可选的,只要有一个词项匹配即可。 搜索 foo bar baz 将找到包含 foobarbaz 中的一个或多个的任何文档。 我们在上面已经讨论了 default_operator,它允许你强制所有的词项都是必需的,但是也有一些布尔运算符可以在查询字符串本身中使用,以提供更多的控制。

首选运算符是 + (该词项必须存在) 和 - (该词项 必须不 存在)。所有其他词项都是可选的。 例如,下面这个查询:

quick brown +fox -news

说明:

  • fox 必须存在
  • news 必须不存在
  • quickbrown 是可选的,但如果他们存在则会增加相关性

我们所熟悉的布尔运算符ANDORNOT(也写成 &&||!)也是受支持的,但要注意它们不遵守通常的优先规则,所以当多个运算符一起使用时,应该使用括号。 例如,前面的查询(即: quick brown +fox -news)可以重写为:

((quick AND fox) OR (brown AND fox) OR fox) AND NOT news
这种形式现在正确地复制了原查询的逻辑,但是相关性评分与原查询几乎没有相似之处。

相比之下,使用 match查询 重写的相同查询会像这样:

{
    "bool": {
        "must":     { "match": "fox"         },
        "should":   { "match": "quick brown" },
        "must_not": { "match": "news"        }
    }
}
分组 (grouping)

多个词项或子句可以用括号组合在一起,形成子查询:

(quick OR brown) AND fox

组可用于针对特定字段,或增强子查询的结果:

status:(active OR pending) title:(full text search)^2
保留字符

如果你需要在查询本身中使用任何起运算符作用的字符(而不是运算符),那么你应该在前面加一个反斜杠对它们进行转义。 例如,要搜索 (1+1)=2,你需要将查询写成 \(1\+1\)\=2。 当请求体使用 JSON 时,前面需要两个反斜杠(\\);反斜杠是 JSON 字符串中保留的转义字符。

GET /twitter/_search
{
  "query" : {
    "query_string" : {
      "query" : "kimchy\\!",
      "fields"  : ["user"]
    }
  }
}

保留字符有:+ - = && || > < ! ( ) { } [ ] ^ " ~ * ? : \ /

未能正确转义这些特殊字符可能会导致语法错误,从而使查询无法运行。

<> 根本不能进行转义。 防止他们试图创建范围查询的唯一方法是将他们从查询字符串中完全删除。

空格和空查询 (whitespaces and empty queries)

空格(whitespace)不被当做运算符。

如果查询字符串为空或者只包含空格,查询将产生一个空的结果集。

避免对嵌套文档使用 query_string 查询

query_string 搜索不会返回 嵌套的(nested) 文档。 要搜索嵌套文档,请使用 nested 查询

搜索多个字段

可以使用 fields 参数同时对多个字段执行 query_string 搜索。

对多个字段运行 query_string 查询的想法是将每个查询词项扩展为一个 OR 子句,如下所示:

field1:query_term OR field2:query_term | ...

例如,这个查询

GET /_search
{
    "query": {
        "query_string" : {
            "fields" : ["content", "name"],
            "query" : "this AND that"
        }
    }
}

与下面这个查询匹配相同的词:

GET /_search
{
    "query": {
        "query_string": {
            "query": "(content:this OR name:this) AND (content:that OR name:that)"
        }
    }
}

由于几个查询是从单个搜索词项中生成的,所以使用带有 tie_breakerdis_max 查询自动完成对它们的组合。 例如(使用符号 ^5name 增加 5):

GET /_search
{
    "query": {
        "query_string" : {
            "fields" : ["content", "name^5"],
            "query" : "this AND that OR thus",
            "tie_breaker" : 0
        }
    }
}

简单通配符也可以用于“在”文档指定的内部元素中搜索。 例如,如果有一个包含多个字段的 city 对象(或包含几个字段的内部对象),则可以自动搜索所有"city"字段:

GET /_search
{
    "query": {
        "query_string" : {
            "fields" : ["city.*"],
            "query" : "this AND that OR thus"
        }
    }
}

另一个选项是在查询字符串本身中提供通配符字段搜索(正确转义 * 标志),例如:city.\*:something

GET /_search
{
    "query": {
        "query_string" : {
            "query" : "city.\\*:(this AND that OR thus)"
        }
    }
}

由于 \ (反斜杠)是 json 字符串中的一个特殊字符,因此需要转义,因此在上面的 query_string中有两个反斜杠。

fields 参数还可以包括基于模式的字段名,允许自动展开到相关字段(包括动态引入的字段)。例如:

GET /_search
{
    "query": {
        "query_string" : {
            "fields" : ["content", "name.*^5"],
            "query" : "this AND that OR thus"
        }
    }
}
多字段搜索的附加参数

当对多个字段运行 query_string 查询时,支持下列附加参数。

type

(可选, string) 确定查询如何对文档进行匹配和评分。有效值有:

best_fields (默认)
查找与任何字段匹配的文档,并使用任何匹配字段中的最高的 _score。 参见 best_fields
bool_prefix
在每个字段上创建 match_bool_prefix 查询,并组合每个字段的 _score。 参见 bool_prefix
cross_fields
用相同的 analyzer 处理字段,就好像它们是一个大字段。 在 任何 字段中查找每个单词。 参见 cross_fields
most_fields
查找与任何字段匹配的文档,并合并每个字段的 _score。参见 most_fields
phrase
See phrase and phrase_prefix. 对每个字段运行 match_phrase 查询,并使用最佳字段(best field)的 _score。 参见 phrasephrase_prefix
phrase_prefix
对每个字段运行 match_phrase_prefix 查询,并使用最佳字段(best field)的 _score。 参见 phrasephrase_prefix

注意:根据 type 的值,multi_match 可能有额外的顶级参数。

同义词与query_string查询

query_string 查询支持 synonym_graph 词元过滤器(token filter)的多词项同义词扩展。 当使用该过滤器时,解析器将为每个多词项同义词创建一个短语查询。 例如,同义词 ny, new york 将产生:

(ny OR ("new york"))

还可以用"逻辑与"匹配多个词项同义词代替:

GET /_search
{
   "query": {
       "query_string" : {
           "default_field": "title",
           "query" : "ny city",
           "auto_generate_synonyms_phrase_query" : false
       }
   }
}

上面的示例创建了一个bool查询:

(ny OR (new AND york)) city

它将文档与词项 ny 或 逻辑与new AND york 相匹配。 默认情况下,参数 auto_generate_synonyms_phrase_query 设置为 true

minimum_should_match 是如何工作的

query_string 根据每个运算符拆分查询,从而为整个输入创建布尔查询。 可以使用minimum_should_match来控制结果查询中应该匹配的“should”子句的数量。

GET /_search
{
    "query": {
        "query_string": {
            "fields": [
                "title"
            ],
            "query": "this that thus",
            "minimum_should_match": 2
        }
    }
}

上面的例子创建了一个bool查询:

(title:this title:that title:thus)~2

它将返回单个字段title与至少thisthatthus 中的2个词项匹配的文档。

minimum_should_match 如何处理多个字段的匹配

GET /_search
{
    "query": {
        "query_string": {
            "fields": [
                "title",
                "content"
            ],
            "query": "this that thus",
            "minimum_should_match": 2
        }
    }
}

上面的例子创建了一个bool查询:

((content:this content:that content:thus) | (title:this title:that title:thus))

它使用"逻辑或"最大限度的通过titlecontent字段去匹配文档。 这里无法应用minimum_should_match参数。

GET /_search
{
    "query": {
        "query_string": {
            "fields": [
                "title",
                "content"
            ],
            "query": "this OR that OR thus",
            "minimum_should_match": 2
        }
    }
}

添加显式运算符(OR)强制每个词项被视为一个单独的子句。

上面的例子创建了一个bool查询:

((content:this | title:this) (content:that | title:that) (content:thus | title:thus))~2

这使文档至少与三个“should”子句中的两个匹配,每个子句都是由每个词项的字段上的最大"逻辑或"构成的。

minimum_should_match 如何处理跨字段搜索

字段type的值为cross_fields时,对在分析输入时使用了相同分析器的字段进行分组。

GET /_search
{
    "query": {
        "query_string": {
            "fields": [
                "title",
                "content"
            ],
            "query": "this OR that OR thus",
            "type": "cross_fields",
            "minimum_should_match": 2
        }
    }
}

上面的例子创建了一个bool查询:

(blended(terms:[field2:this, field1:this]) blended(terms:[field2:that, field1:that]) blended(terms:[field2:thus, field1:thus]))~2

这将匹配与三个词项混合(blended)查询中的至少两个匹配的文档。

注意

允许执行昂贵的查询

查询字符串查询可以在内部转换为prefix查询,这意味着如果如这里所解释的那样禁用前缀查询,则查询字符串查询将不会被执行并抛出异常。