Elasticsearch Query DSL 语言介绍
0. 引言
Elasticsearch 提供了强大的查询语言 Query DSL(Domian Specific Language)。Query DSL 是基于 JSON 数据格式来描述查询条件。本文的主要介绍如何使用 Query DSL ,包括语法规则和字段使用,同时配有相应例子供大家参考。
Elasticsearch 查询规则分为两类:Query context (查询上下文) 和 Filter context (过滤上下文)。他们对查询结果有不同的影响。Query 影响查询结果的相关性评分。Elasticsearch 会计算每条查询结果的相关性评分(relevance score),并按评分对结果进行排序。Filter 要求结果完全匹配 filter context 设置的查询条件,不会影响相关性评分。我们可以通过下面例子初步认识 Elasticsearch 查询语音。该查询语句会匹配满足全部以下条件的文档:
- title 字段包含单词 search
- content 字段包含单词 elasticsearch
- status 字段为 published
- publish_date 字段大于 2015 年 1 月
GET /_search
{
"query": {
"bool": {
"must": [
{ "match": { "title": "Search" }},
{ "match": { "content": "Elasticsearch" }}
],
"filter": [
{ "term": { "status": "published" }},
{ "range": { "publish_date": { "gte": "2015-01-01" }}}
]
}
}
}
命中一条结果:
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.5753642,
"hits": [
{
"_index": "twitter",
"_type": "1",
"_id": "NpI0tGwBw88r7mqtr8EN",
"_score": 0.5753642,
"_source": {
"title": "My Search",
"content": "trying out Elasticsearch",
"status": "published",
"publish_date": "2019-11-15T14:12:12"
}
}
]
}
}
接下来,我们就几种常见的查询场景依次介绍。
1. 组合查询
组合查询(Compound Queries)中的 bool query 用于在多个字段上进行组合查询,是一个查询中包含多个查询条件的查询。组合查询接受四种布尔匹配:
- must:必须匹配
- filter:必须匹配(但对评分没有影响)
- should:如果匹配,将增加相关性评分
- must_not:必须不匹配(对评分贡献为0)
每一个子查询都独自地计算文档的相关性得分。每个文档的最终得分 _score 是各个分数的总合。以下是一个典型例子:
POST _search
{
"query": {
"bool" : {
"must" : {
"term" : { "user" : "kimchy" }
},
"filter": {
"term" : { "tag" : "tech" }
},
"must_not" : {
"range" : {
"age" : { "gte" : 10, "lte" : 20 }
}
},
"should" : [
{ "term" : { "tag" : "wow" } },
{ "term" : { "tag" : "elasticsearch" } }
],
"minimum_should_match" : 1,
"boost" : 1.0
}
}
}
注:minimum_should_match 表示至少要满足的 should 语句。例子中有两条 should 语句,要求至少满足一条。
2. 全文搜索
2.1 Match
匹配查询(match query)也是布尔类型的查询。匹配查询会构造一个布尔查询来分析文本。布尔语句之间关系由 operator 字段定义,可选值为 or 和 and,默认是 or。如果是 or 的话,可以使用 minimum_should_match 来设置至少要匹配的 should 语句数量(默认为 1,至少一条)。
以下是一个典型例子。"this is a test" 是查询字符串。match 查询首先将查询字符串解析成一个词项列表,单词之间以非数字字母字符隔开。然后对这些词项进行搜索。筛选出 message 文本中包含`this、is 、a 或 test 至少一个单词的文档。
GET /_search
{
"query": {
"match" : {
"message" : "this is a test"
}
}
}
等价于
GET /_search
{
"query": {
"bool" : {
"should": [
{ "term": { "message": "this" }},
{ "term": { "message": "is" }},
{ "term": { "message": "a" }},
{ "term": { "message": "test" }},
]
}
}
}
2.2 Match Phase
短语匹配(match_phrase query)与匹配查询(match query)类似。但查询结果只保留那些包含全部搜索词项,且位置与搜索词项相同的文档。下面例子仅匹配 title 文本中包含 quick brown fox 短语的文档,且顺序不可变,中间不能夹带其他单词。
什么是短语?
一个被认定为和短语 quick brown fox 匹配的文档,必须满足以下这些要求:
- quick 、 brown 和 fox 需要全部出现在域中。
- brown 的位置应该比 quick 的位置大 1 。
- fox 的位置应该比 quick 的位置大 2 。
如果以上任何一个选项不成立,则该文档不能认定为匹配。
GET /my_index/my_type/_search
{
"query": {
"match_phrase": {
"title": "quick brown fox"
}
}
}
2.3 Multi Match
多字段匹配(multi_match query)是基于 match query 之上,允许同一查询作用在多个字段上。以下例子, match query 同时作用在字段 title 和 以 _name 结尾的字段,比如 first_name 和 last_name。
GET /_search
{
"query": {
"multi_match" : {
"query": "Will Smith",
"fields": [ "title", "*_name" ]
}
}
}
2.4 Query String
查询字符串(query string)支持使用查询字符串语言(Query string syntax)来设置查询条件。
以下例子使用了查询字符串语言,表达式为 (new york city) OR (big apple)。相当于执行两条 match query,查询字符串分别是 new york city 和 big apple。如果要完整匹配短语的话,可以使用引号限定,比如 (new york city) OR ("big apple") 。
GET /_search
{
"query": {
"query_string" : {
"query" : "(new york city) OR (big apple)",
"default_field" : "content"
}
}
}
2.5 Simple Query String
Query String 如果表达式不合法会返回错误。在实际使用中,一般建议使用 Simple Query String。
3. 词项查询
词项查询(term-level queries)基于词项的查询如 term 或 fuzzy 查询不需要分析阶段,它们对单个词项进行操作。查用的词项查询类型有:
3.1 Range query
返回字段在指定范围内的文本
GET _search
{
"query": {
"range" : {
"age" : {
"gte" : 10,
"lte" : 20,
"boost" : 2.0
}
}
}
}
3.2 Term query
返回字段完全匹配指定词项的文档。对于 text 类型的字段查询,建议使用 match query
GET /_search
{
"query": {
"term": {
"user": {
"value": "Kimchy",
"boost": 1.0
}
}
}
}