Elasticsearch DSL 查询
DSL 是 Domain Specific Language(特定领域语言)的缩写。
Elasticsearch 提供了功能丰富且灵活的查询语言,即 DSL 查询。你可以用它构建出更加复杂、功能更加强大的查询语句。
先来一个简单的例子,比如,我们可以这样查询 first_name 字段包含 John 的用户。
GET /alibaba/user/_search
{
"query" : {
"match" : {
"first_name" : "John"
}
}
}
它会返回和上一节中的查询字符串搜索相同的结果。只不过这里我们不再使用查询字符串作为请求参数,而是使用 JSON 格式的请求体。
bool 联合查询
逻辑与(AND)
下面,我们来进行一个稍微复杂点的查询。比如,查询姓氏包含 Smith 且年龄大于 30 岁的用户。
GET /alibaba/user/_search
{
"query" : {
"bool" : {
"filter" : {
"range" : {
"info.age" : { "gt" : 30 }
}
},
"must" : [{
"match" : {
"last_name" : "smith"
}
}]
}
}
}
返回结果:
{
"took": 4,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.2876821,
"hits": [
{
"_index": "alibaba",
"_type": "user",
"_id": "3",
"_score": 0.2876821,
"_source": {
"email": "john3@smith.com",
"first_name": "John3",
"last_name": "Smith",
"full_name": "John3 Smith",
"info": {
"age": 35,
"interests": [
"sports",
"musics"
],
"address": "guangdong shenzhen longhua"
},
"created_at": "2019-06-08 09:40:10"
}
}
]
}
}
查询 last_name 包含 Smith,且 full_name 包含 John 的用户。
GET /alibaba/user/_search
{
"query": {
"bool": {
"must": [
{ "match": { "last_name": "Smith" } },
{ "match": { "full_name": "John" } }
]
}
}
}
返回结果:
{
"took": 4,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.5457982,
"hits": [
{
"_index": "alibaba",
"_type": "user",
"_id": "1",
"_score": 0.5457982,
"_source": {
"email": "john@smith.com",
"first_name": "John",
"last_name": "Smith",
"full_name": "John Smith",
"info": {
"age": 25,
"interests": [
"games",
"musics"
],
"address": "guangdong shenzhen nanshan"
},
"created_at": "2019-06-06 08:30:10"
}
}
]
}
}
逻辑或(OR)
查询 info.age 大于 30 或 info.address 包含 baoan 的用户。
GET /alibaba/user/_search
{
"query": {
"bool": {
"should": [{
"range": {
"info.age": {
"gt": 30
}
}
},
{
"match": {
"info.address": "baoan"
}
}
]
}
}
}
返回结果:
{
"took": 8,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 1,
"hits": [
{
"_index": "alibaba",
"_type": "user",
"_id": "3",
"_score": 1,
"_source": {
"email": "john3@smith.com",
"first_name": "John3",
"last_name": "Smith",
"full_name": "John3 Smith",
"info": {
"age": 35,
"interests": [
"sports",
"musics"
],
"address": "guangdong shenzhen longhua"
},
"created_at": "2019-06-08 09:40:10"
}
},
{
"_index": "alibaba",
"_type": "user",
"_id": "2",
"_score": 0.25316024,
"_source": {
"email": "john2@smith.com",
"first_name": "John2",
"last_name": "Smith",
"full_name": "John2 Smith",
"info": {
"age": 28,
"interests": [
"games",
"books"
],
"address": "guangdong shenzhen baoan"
},
"created_at": "2019-06-07 08:30:10"
}
}
]
}
}
查询 last_name 包含 Smith,或者 full_name 包含 John 的用户。
GET /alibaba/user/_search
{
"query": {
"bool": {
"should": [
{ "match": { "last_name": "Smith" } },
{ "match": { "full_name": "John" } }
]
}
}
}
返回结果:
{
"took": 7,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 0.5457982,
"hits": [
{
"_index": "alibaba",
"_type": "user",
"_id": "1",
"_score": 0.5457982,
"_source": {
"email": "john@smith.com",
"first_name": "John",
"last_name": "Smith",
"full_name": "John Smith",
"info": {
"age": 25,
"interests": [
"games",
"musics"
],
"address": "guangdong shenzhen nanshan"
},
"created_at": "2019-06-06 08:30:10"
}
},
{
"_index": "alibaba",
"_type": "user",
"_id": "2",
"_score": 0.2876821,
"_source": {
"email": "john2@smith.com",
"first_name": "John2",
"last_name": "Smith",
"full_name": "John2 Smith",
"info": {
"age": 28,
"interests": [
"games",
"books"
],
"address": "guangdong shenzhen baoan"
},
"created_at": "2019-06-07 08:30:10"
}
},
{
"_index": "alibaba",
"_type": "user",
"_id": "3",
"_score": 0.2876821,
"_source": {
"email": "john3@smith.com",
"first_name": "John3",
"last_name": "Smith",
"full_name": "John3 Smith",
"info": {
"age": 35,
"interests": [
"sports",
"musics"
],
"address": "guangdong shenzhen longhua"
},
"created_at": "2019-06-08 09:40:10"
}
}
]
}
}
总结说明
- bool:表示联合查询,用来合并多种查询条件。
- must:表示多个查询条件的肯定匹配,多个条件必须都满足,相当于 and。
- should:表示多个查询条件的肯定匹配,多个条件只要有一个满足,相当于 or。
- must_not:表示多个查询条件的否定匹配,多个条件必须都满足,相当于 and。
- filter:用于快速过滤结果集。
- 文档字段的内部字段,通过 . 号来访问,如 info.age。
全文搜索
这里,我们搜索 info.address 包含 “shenzhen baoan” 的用户。
GET /alibaba/user/_search
{
"query" : {
"match" : {
"info.address" : "shenzhen baoan"
}
}
}
返回结果:
{
"took": 5,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 0.5063205,
"hits": [
{
"_index": "alibaba",
"_type": "user",
"_id": "2",
"_score": 0.5063205,
"_source": {
"email": "john2@smith.com",
"first_name": "John2",
"last_name": "Smith",
"full_name": "John2 Smith",
"info": {
"age": 28,
"interests": [
"games",
"books"
],
"address": "guangdong shenzhen baoan"
},
"created_at": "2019-06-07 08:30:10"
}
},
{
"_index": "alibaba",
"_type": "user",
"_id": "1",
"_score": 0.25316024,
"_source": {
"email": "john@smith.com",
"first_name": "John",
"last_name": "Smith",
"full_name": "John Smith",
"info": {
"age": 25,
"interests": [
"games",
"musics"
],
"address": "guangdong shenzhen nanshan"
},
"created_at": "2019-06-06 08:30:10"
}
},
{
"_index": "alibaba",
"_type": "user",
"_id": "3",
"_score": 0.25316024,
"_source": {
"email": "john3@smith.com",
"first_name": "John3",
"last_name": "Smith",
"full_name": "John3 Smith",
"info": {
"age": 35,
"interests": [
"sports",
"musics"
],
"address": "guangdong shenzhen longhua"
},
"created_at": "2019-06-08 09:40:10"
}
}
]
}
}
可以发现,Elasticsearch 自动把要搜索匹配的字符串 “shenzhen baoan”,拆分成了两个词 “shenzhen” 和 “baoan”。然后再到 info.address 中进行全文搜索匹配。
搜索到的 3 条记录,默认是按照搜索排名分数降序排列的。
搜索排名分数(score),就是搜索结果相关性大小的评分,即文档与查询条件的匹配程度。相关性越大,搜索排名分数就越高,排名(排序)就越靠前。
这个概念在传统的关系型数据库中是无法想象的。
上面的查询语句,等价于下面的这种写法:
GET /alibaba/user/_search
{
"query" : {
"bool":{
"should": [
{"match" : {"info.address" : "shenzhen"}},
{"match" : {"info.address" : "baoan"}}
]
}
}
}
短语搜索
有时,我们确切地想要匹配多个单词或者短语(phrase)。这时,可以采用 match_phrase 来实现。
GET /alibaba/user/_search
{
"query" : {
"match_phrase" : {
"info.address" : "shenzhen baoan"
}
}
}
返回结果:
{
"took": 21,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.5063205,
"hits": [
{
"_index": "alibaba",
"_type": "user",
"_id": "2",
"_score": 0.5063205,
"_source": {
"email": "john2@smith.com",
"first_name": "John2",
"last_name": "Smith",
"full_name": "John2 Smith",
"info": {
"age": 28,
"interests": [
"games",
"books"
],
"address": "guangdong shenzhen baoan"
},
"created_at": "2019-06-07 08:30:10"
}
}
]
}
}
高亮显示
有时,我们需要高亮显示匹配到的关键字。可以通过 highlight 来实现。
GET /alibaba/user/_search
{
"query" : {
"match_phrase" : {
"info.address" : "shenzhen baoan"
}
},
"highlight": {
"fields" : {
"info.address" : {}
}
}
}
返回结果:
{
"took": 77,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.5063205,
"hits": [
{
"_index": "alibaba",
"_type": "user",
"_id": "2",
"_score": 0.5063205,
"_source": {
"email": "john2@smith.com",
"first_name": "John2",
"last_name": "Smith",
"full_name": "John2 Smith",
"info": {
"age": 28,
"interests": [
"games",
"books"
],
"address": "guangdong shenzhen baoan"
},
"created_at": "2019-06-07 08:30:10"
},
"highlight": {
"info.address": [
"guangdong <em>shenzhen</em> <em>baoan</em>"
]
}
}
]
}
}
多字段搜索
有时,我们想要让同一个查询字符串同时应用到多个字段进行搜索匹配。可以采用 multi_match 来实现。
例如,查询 first_name 或者 full_name 包含 “smith” 的文档。
GET /alibaba/user/_search
{
"query" : {
"multi_match": {
"query": "smith",
"fields": ["first_name", "full_name"]
}
}
}
还没有评论,来说两句吧...