Skip to main content

查询语言参考

Pseudo-grammar

query = '(' query ')'
| query operator query
| unary_operator query
| query query
| clause

operator = 'AND' | 'OR'

unary_operator = 'NOT' | '-'

clause = field_name ':' field_clause
| defaultable_clause
| '*'

field_clause = term | term_prefix | term_set | phrase | phrase_prefix | range | '*'
defaultable_clause = term | term_prefix | term_set | phrase | phrase_prefix

编写查询

逃逸特殊字符

某些字符在非引号项中需要进行逃逸,因为它们在语法上具有特殊意义:特殊保留字符包括:+^`:{}"[]()~!\\*空格。如果这些字符出现在查询项中,需要通过在其前面加上反斜杠 \ 来进行逃逸。

在使用引号项中,当前使用的引号字符 '" 需要进行逃逸。

字段名称中的允许字符

参见 字段名称验证规则 在索引配置文档中。

处理嵌套结构

存储在如 objectjson 字段等深层嵌套数据结构中的数据可以通过在字段名称中使用点作为分隔符来引用。 例如,文档 {"product": {"attributes": {"color": "red"}}} 可以通过以下方式匹配:

product.attributes.color:red

如果对象的键包含点,则上述语法会存在一些歧义:默认情况下 {"k8s.component.name": "quickwit"} 将会被以下方式匹配: k8s.component.name:quickwit

可以通过在 JSON 字段配置中设置 expand_dots 来消除这种歧义。 在这种情况下,需要在查询中对 . 进行逃逸,以匹配此文档,如下所示:

k8s\.component\.name:quickwit

结构化数据

日期时间

日期时间值必须提供为 rfc3339 格式,例如 1970-01-01T00:00:00Z

IP 地址

IP 地址可以提供为 IPv4 或 IPv6。建议使用索引文档时使用的格式进行搜索。 不支持使用 CIDR 表示法搜索 IP 范围,但可以使用普通的范围查询。


子句类型

术语 field:term

term = term_char+

如果目标字段包含等于提供的术语的标记,则匹配文档。

field:value 将匹配任何字段 'field' 中有标记 'value' 的文档。

术语前缀 field:prefix*

term_prefix = term '*'

如果目标字段包含以提供的值开头的标记,则匹配文档。

field:quick* 将匹配任何字段 'field' 中有类似 quickwitquickstart 的标记的文档,但不会匹配 quiabcd

术语集合 field:IN [a b c]

term_set = 'IN' '[' term_list ']'
term_list = term_list term
| term

如果文档包含提供的任一标记,则匹配。

示例

field:IN [ab cd] 将匹配 'ab' 或 'cd',但不会匹配其他内容。

性能说明

这很像编写 field:ab OR field:cd。当只有少量术语需要搜索时,使用 OR 通常更快。 当有许多值需要匹配时,术语集合查询可能会变得更加高效。

短语 field:"sequence of words"

phrase = phrase_string
| phrase_string slop
phrase_string = '"' phrase_char '"'
slop = '~' [01-9]+

如果字段包含提供的标记序列,则匹配。field:"looks good to me" 将匹配任何包含该序列的文档。 该字段在索引时必须配置为 record: position

Slop 运算符

也可以添加一个斜距(slop),允许在有一定距离的情况下匹配序列。例如,"looks to me"~1 将匹配 "looks good to me",但不会匹配 "looks very good to me"。 换位成本为 2,例如,"A B"~1 不会匹配 "B A",但如果使用 "A B"~2 则会匹配。 换位不是特殊情况,在上面的例子中,A 移动了 1 个位置,B 也移动了 1 个位置,因此斜距为 2。

短语前缀 field:"finish this phr"*

phrase_prefix = phrase '*'

如果字段包含提供的标记序列,并且查询中的最后一个标记可能是文档中标记的前缀,则匹配。

该字段在索引时必须配置为 record: position

短语前缀查询没有斜距。

示例

field:"thanks for your contrib"* 将匹配 'thanks for your contribution'。

限制

在某些情况下,Quickwit 可能会修剪通过此子句匹配的一些结果。如果你搜索 "thanks for your co"*,它将枚举前 50 个以 "co" 开头的标记(按存储顺序),并搜索任何 "thanks for your" 后面跟着这些标记之一的文档。

如果有许多以 "co" 开头的标记,"contribution" 可能不会是被选中的 50 个标记之一,因此查询将无法匹配包含 "thanks for your contribution" 的文档。普通的前缀查询不会出现这个问题。

范围 field:[low_bound TO high_bound}

range = explicit_range | comparison_half_range

explicit_range = left_bound_char bounds right_bound_char
left_bound_char = '[' | '{'
right_bound_char = '}' | ']'
bounds = term TO term
| term TO '*'
| '*' TO term

comparison_range = comparison_operator term
comparison_operator = '<' | '>' | '<=' | '>='

如果文档在指定字段内包含位于给定范围内的标记,则匹配。 对于范围查询,必须提供一个字段。Quickwit 不会自动使用 default_search_fields

顺序

对于文本字段,范围由 UTF-8 编码字节数组的字典序定义。这意味着对于文本字段,100 位于 1 和 2 之间。

在整数上使用范围时,行为是自然的。

包含和排除边界

包含边界用方括号 [] 表示。它们会匹配等于边界术语的标记。 排除边界用花括号 {} 表示。它们不会匹配等于边界术语的标记。

半开区间

你可以使用 * 作为其中一个边界来创建半开区间。field:[b TO *] 将匹配 'bb' 和 'zz',但不会匹配 'ab'。 你也可以使用基于比较的语法:field:<bfield:>bfield:<=bfield:>=b

示例
  • 包含区间:ip:[127.0.0.1 TO 127.0.0.50]
  • 排除区间:ip:{127.0.0.1 TO 127.0.0.50}
  • 无上限包含区间:ip:[127.0.0.1 TO *]ip:>=127.0.0.1
  • 无上限排除区间:ip:{127.0.0.1 TO *}ip:>127.0.0.1

存在 field:*

匹配设置了指定字段的文档。你必须为此查询指定一个字段,Quickwit 不会自动使用 default_search_fields

匹配所有 *

匹配所有文档。你不能在前面加上字段。它简单地表示为 *


构建查询

大多数查询由多个子句组成。在这种情况下,可以在子句之间添加操作符。

如果没有提供操作符,默认隐式使用 AND

连接 AND

AND 查询只有在两边都匹配时才会匹配。

选择 OR

OR 查询只要其中一边(或两边)匹配就会匹配。

否定 NOT-

NOT 查询在其应用的子句不匹配时会匹配。 前缀 - 等价于 NOT 操作符。

分组 ()

括号用于强制操作符的计算顺序。 例如,如果查询在 'field1' 是 'one' 或 'two',并且 'field2' 是 'three' 时应匹配,可以使用 (field1:one OR field1:two) AND field2:three

操作符优先级

没有括号时,AND 的优先级高于 OR。也就是说,a AND b OR c 被解释为 (a AND b) OR c

NOT- 的优先级最高,因此 -a AND b 意味着 (-a) AND b,而不是 -(a AND b)


其他考虑因素

默认搜索字段

在许多情况下,如果在索引配置的 default_search_fields 数组中配置了要搜索的字段,则可以省略该字段。如果配置了多个默认字段,则生成的隐式子句将使用连接(OR)组合起来。

分词

请注意,查询的结果可能取决于用于搜索字段的分词器。因此,本文档始终提到的是标记,这些标记可能是文档包含的确切值(在原始分词器的情况下),或者是其子集(例如,任何在空格处分割的分词器)。