query_string 是 ES DSL 查询中最为强大的查询语句,支持非常复杂的语法,适合用来做自己的搜索引擎
一、语法
GET /_search
{
"query": {
"query_string": {
"query": "(new york city) OR (big apple)",
"default_field": "content"
}
}
}
1. 字段名 Field names
在查询中,可以指定字段名,格式为:
语法包含但不限于字段名:值(例如:status:active,字段status,值为active的文档)
(title:(quick OR brown),字段title出现 quick或 brwon)
(author:"John Smith",字段author为短语 John Smith)
(first\ name:Alice,字段“first name”值为 Alice)
(book.\*:(quick OR brown),字段book.title, book.content或book.date字段包含 quick 或 brown)
(_exists_:title,字段title 包含任意非空值)
2. 通配符 Wildcards
用于单独的 terms,使用 ? 替换单独字符, * 号替换0到多个字符
例如:qu?ck bro*
【警惕】通配符查询需要使用大量内存,性能很差;另一种情况是以通配符开头的单词,查询起来非常笨重,因为需要遍历所有的terms,避免这一情况,设置参数 allow_leading_wildcard 为false
(此外,纯粹的通配符 * 将被替换为 exists 查询,这是为了提高效率,结果就是,“field:*”会匹配"",如
{
"field": ""
}
但不会匹配 空值
{
"field": null
}
3. 正则表达式 Regular expressions
正则表达式可以嵌入到 query string中,格式为用 "/" 符号包围正则表达式:
name:/joh?n(ath[oa]n)/
【注意】, allow_leading_wildcard 参数对正则表达式不起效, /.*n/ 仍然会遍历所有的term
4. 模糊匹配 Fuzziness
执行 fuzzy 查询,使用 ~ 操作符
quikc~ brwn~ foks~
默认的编辑距离是2,但是一般编辑距离1就可以解决 80% 的认类错误拼写,可以指定距离1:
quikc~1
将 fuzziness 和通配符混合是不支持的,一旦混合,其中一个操作符将失效,例如搜索 app*~1不应用 fuzzy 操作符
5. 邻近搜索 Proximity searches
短语查询(例如 "john smith")期望所有 terms 的顺序不变,但邻近查询允许指定单词离得稍微远一些,或有不同的顺序。 fuzzy 查询可以指定字符在单词中的编辑距离,同样,邻近搜索允许指定短语中单词的最大编辑距离:
"fox quick"~5
相关度与匹配文本的接近程度有关,比如上述的查询中, "quick fox" 比 "quick brown fox" 相关性更高
6. 范围 Ranges
范围可以指定 date、numeric 或 string 字段,包含范围用方括号指定首尾范围 [min TO max],排除范围用花括号 {min TO max}
date:[2012-01-01 TO 2012-12-31],2012的所有日期
count:[1 TO 5],数字 1..5
tag:{alpha TO omega},在 alpha 到 omega 之间的标签,排除 alpha 和 omega
count:[10 TO *],从10开始的数字
date:{* TO 2012-01-01},2012年以前的日期
count:[1 TO 5} 数字1..4,不包含5
一边没有边界的范围查询可以用以下语法:
age:>10
age:>=10
age:<10
age:<=10
age:(>=10 AND <20)
age:(+>=10 +<20),这里的 +是 AND 操作符
7. 加权 Boosting
使用 boost 操作符 ^ 让一个 term 更相关。例如想找关于 foxes 的文档,但我们更关心 quick foxes:
quick^2 fox
默认的 boost 值为1,可以用0到1的浮点数来减小相关性
加权重可以用到短语或组:
"john smith"^2 (foo bar)^4
8. 布尔操作符
默认情况下,一旦一个 term 匹配了,所有 terms 都是可选的。一个搜索 foo bar baz 将找到所有包含这其中一个或多个单词的文档。 default_operator 参数允许修改这个默认布尔逻辑。但布尔操作符可以用来在 query string 中提供更多控制
+:必须出现
-:不许出现
例如
quick brown +fox -news
,必须出现 fox,不许出现 news,quick 和 brown 的出现会提高相关度
类似的操作符AND, OR, NOT (也写作 &&, ||, !)
,需要注意他们不遵循优先规则,因此需要用圆括号来区分多操作符中的优先级,例如前面的查询可以写为:
((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"}
}
}
9. 分组 Grouping
圆括号可以用来给多个 terms
或从句分组,也可以用来给一个字段名指定目标,给一个结果修改权重
(quick OR brown) AND fox
status:(active OR pending) title:(full text search)^2
10. 转义字符(保留字) Reserved characters
如果你的查询中,存在可以作为操作符的字符,并且你不想用来作为操作符,则需要使用反斜杠来转义。
例如,搜索(1+1)=2
,你需要写为"\(1\+1\)\=2"
,如果写为 JSON作为请求体,需要用到双反斜杠(\\)
,因为反斜杠是 JSON 字符串的保留转义字符
保留字有:
+ - = && || > < ! ( ) { } [ ] ^ " ~ * ? : \ /
【注意】 < 和 > 符号不能被转义,唯一可以避免误创建范围查询的方法,就是完全不在查询中出现该符号
11. 空格和空查询
空格不被认为是操作符
如果 query string 是空,或者只包含空格,查询将返回空结果
12. 避免使用 query_string 查询 nested 文档
query_string 搜索不返回 nested 文档,想要查询 nested 文档,使用 nested 查询
13. 搜索多字段
使用 fields 参数来执行 query_string 搜索多字段
使用 query_string 来搜索多字段的方法,是扩展每个查询 term 为 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)"
}
}
}
14. 多字段查询的其他参数
当运行 query_string 查询使用多字段时,支持以下附加参数,类似multi_match
type:
决定如何匹配查询,给文档打分,可用的值有:
15. 同义词 Synonyms and the query_string query
query_string 用 synonym_graph token filter
支持多 term 同义词扩展,当使用了这个 filter,解析器给每个多 term 同义词创建短语查询
16. minimum_should_match 如何工作
query_string 根据操作符分隔每个查询,构造一个布尔查询作为整个输入。你可以用 minimum_shuould_match
参数来控制 should 从句中有多少需要得到匹配。
布尔查询
(title:this title:that title:thus)~2
等价于
GET /_search
{
"query": {
"query_string": {
"fields": [
"title"
],
"query": "this that thus",
"minimum_should_match": 2
}
}
}
17. minimum_should_match 如何作用于多字段查询(multiple fields)
布尔查询
((content:this content:that content:thus) | (title:this title:that title:thus))
等价于
GET /_search
{
"query": {
"query_string": {
"fields": [
"title",
"content"
],
"query": "this that thus",
"minimum_should_match": 2
}
}
}
布尔查询
((content:this | title:this) (content:that | title:that) (content:thus | title:thus))~2
等价于
GET /_search
{
"query": {
"query_string": {
"fields": [
"title",
"content"
],
"query": "this OR that OR thus",
"minimum_should_match": 2
}
}
}
18. minimum_should_match 如何作用于 cross-field 搜索
布尔查询
(blended(terms:[field2:this, field1:this]) blended(terms:[field2:that, field1:that]) blended(terms:[field2:thus, field1:thus]))~2
等价于
GET /_search
{
"query": {
"query_string": {
"fields": [
"title",
"content"
],
"query": "this OR that OR thus",
"type": "cross_fields",
"minimum_should_match": 2
}
}
}