基本字段概念:
- query:查询语句,开头唯一标识件
- must:且,算 score
- should:或,算 score
- filter:且,不算 score,可以使用缓存
- bool:组合过滤器,可以接受多个其他过滤器作为参数,并将这些过滤器结合成各式各样的布尔(逻辑)组合
- sort:排序字段
- from和size:分页字段
- nested:单独类型特殊查询规则:
-
{ "query": { "bool": { "filter": [ { "term": { "code": "2tT0R2tqnMy7A" } }, { "nested": { "path": "tagList", "query": { "bool": { "filter": [ { "terms": { "tagList.key": [ "contentQuality", "contentConsume" ] } } // { // "multi_match": { // "query": "高价值内容", // "fields": [ // "tagList.showTag" // ] // } // } ] } } } } ] } }, "sort": [ { "publishTime": { "order": "desc", "unmapped_type": "long" } } ], "from": 0, "size": 10 }
-
组合规则:
其中排序和分页都很简单,复杂的就是query,我们遵循的最基本规则:
- 所有的 filter、must、must_not、should 都必须跟在 bool 后面,可以互相嵌套,但是外层必须是 bool
- match:嵌套在 must 或 should 里,算 score,可以通过 analyzer 指定分词器
- filter:用于只过滤,但并不参与计算score(比如:query.bool.filter.bool.must就不会计算score,而query.bool.must就会参与计算score)。
- should:里面包含的条件满足规定个数即可,个数通过紧跟在后面的minimum_should_match字段决定,值为整数或百分比,表示should中的条件最少命中几个或百分之多少。可以跟在最外层的bool中,此时参与score计算,或者放在filter里面的嵌套bool中,此时不参与score计算。
- must:用来匹配等于查询,可以跟在最外层的bool中,此时参与score计算,或者放在filter里面的嵌套bool中,此时不参与score计算。里面可以包含term(=),terms(in),match(like),multi_match(multi like),range(范围:gte大于等于,gt大于,lte小于等于,lt小于)。
- must_not:用来匹配不等于查询,可以跟在最外层的bool中,此时参与score计算,或者放在filter里面的嵌套bool中,此时不参与score计算。里面可以包含term(!=),terms(not in),match(not like),multi_match(multi not like),range(范围:gte不大于等于,gt不大于,lte不小于等于,lt不小于)。
- term(=),terms(in),match(like),multi_match(multi like),range(范围:gte大于等于,gt大于,lte小于等于,lt小于),可以包含在filter、must、must_not、should中。
- exists用在filler中,用于查找在特定字段(field字段规定)有值的记录,无论值是多少。
- missing用在filter中,用于查找在特定字段(field字段规定)里没有值,或者是映射时指定的默认值的记录(通过设置existence和null_value字段都为true实现)。
注意,过滤关键字对存储类型有一定限制:
term/tems | 支持 long、keyword,不支持text |
灵活的match操作
match查询默认使用OR操作符,例如搜索文本“ES WHY”,那么会同时匹配 “ES 1”和"1 WHY",为了搜索同时包含 "ES"和“WHY”关键词的结果,将match字段的name修改为一个映射,并将operator字段设置为and,查询如下:
{
"query":{
"match": {
"name":{
"query":"ES WHY",
"operator":"and"
}
}
}
}
当我们只记住一个关键字的部分词,且不是连续时,可以用phrase类型查询,stop代表移动几个位置可以变为搜索的关键字。比入搜索name字段包含“ES and WHY”,我们忘记了中间的“and”,只记得“ES”和“AND”,那么可以用下面的查询:
{
"query":{
"match": {
"name":{
"type":"phrase",
"query":"ES WHY",
"stop": 1
}
}
}
}
当我们要进行前缀匹配时,比如提供搜索框里的自动联想功能,可以用pharse_prefix查询,并且最好通过max_expansions来设置满足前缀的结果返回数量。比如我们要搜索所有name字段以ES开头的记录,并限制返回10条,DSL如下:
{
"query":{
"match": {
"name":{
"type":"phrase_prefix",
"query":"ES",
"max_expansions": 10
}
}
}
}
如果需要至少匹配到分词后的一个关键字,需要用 must + match/multi_match:
{
"query":{
"must": {
"multi_match": {
"query" : "搜索内容",
"fields" : ["title", "content"]
}
}
}
}
DSL:
filter:
where
supply_list.new_product_id in (8048, 8426)
and status = 1
and ( supply_list.category_lv1 in (41, 65, 16, 14, 54) ) or ( category_lv1 = 32 and category_lv2 = 93 )
should:
supply_list.product_name like '%西瓜,荔枝%'
supply_list.address like '%荔枝%'
name like '%荔枝%'
三者满足最少一个
sort:
order by updated_time desc
from和size:
limit 0 10
对应的DSL:
{
"query": {
"bool": {
"filter": {
"bool": {
"must": [
{
"terms":{
"supply_list.new_product_id":[
8048,8426
]
}
},
{
"term": {
"status": 1
}
},
{
"bool": {
"should": [
{
"terms": {
"supply_list.category_lv1": [
41,
65,
16,
14,
54
]
}
},
{
"bool": {
"must": [
{
"term": {
"supply_list.category_lv1": 32
}
},
{
"term": {
"supply_list.category_lv2": 93
}
}
]
}
}
]
}
}
]
}
},
"should": [
{
"match": {
"supply_list.product_name": "荔枝,西瓜"
}
},
{
"match": {
"supply_list.address": "荔枝"
}
},
{
"match": {
"name": "荔枝"
}
}
],
"minimum_should_match": 1
}
},
"sort": [
{
"updated_time": {
"order": "desc",
"unmapped_type": "long"
}
}
],
"from": 0,
"size": 10
}
结果(只贴了3个,实际返回了10个):
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 157,
"max_score": null,
"hits": [
{
"_index": "supplier",
"_type": "detail",
"_id": "866811963195144",
"_score": null,
"_source": {
"id": 189834,
"customer_id": 866811963195144,
"name": "游客7058",
"identity": "",
"summary": "",
"status": 1,
"follow_status": 1,
"created_time": 1591369119,
"updated_time": 1591369119,
"supply": "西瓜",
"staff_id": 0,
"is_assign": 0,
"next_time": 0,
"merchandiser_id": 0,
"experience": "",
"is_new": 1,
"attitude": "",
"share_id": "",
"source": 0,
"cooperation": 0,
"headpic": "",
"supply_list": [
{
"id": 195753,
"product_id": 8426,
"product_name": "西瓜",
"supplier_id": 866811963195144,
"province_id": 24,
"city_id": 397,
"county_id": 2644,
"location_id": 2644,
"address": "贵州黔西南望谟县",
"start_time": 0,
"end_time": 0,
"product_amount": "8000斤",
"product_info": null,
"market_name": "",
"status": 3,
"supply_status": 1,
"created_time": 1591369119,
"updated_time": 1591369119,
"target_city": "[]",
"source": 0,
"new_product_id": 8426,
"new_breed_id": 0,
"category_lv1": 65,
"category_lv2": 142
}
]
},
"sort": [
1591369119
]
},
{
"_index": "supplier",
"_type": "detail",
"_id": "246208843195136",
"_score": null,
"_source": {
"id": 189820,
"customer_id": 246208843195136,
"name": "黄福兵",
"identity": "",
"summary": "",
"status": 1,
"follow_status": 1,
"created_time": 1591368395,
"updated_time": 1591368395,
"supply": "西瓜",
"staff_id": 0,
"is_assign": 0,
"next_time": 0,
"merchandiser_id": 0,
"experience": "",
"is_new": 1,
"attitude": "",
"share_id": "",
"source": 0,
"cooperation": 0,
"headpic": "",
"supply_list": [
{
"id": 195739,
"product_id": 8426,
"product_name": "西瓜",
"supplier_id": 246208843195136,
"province_id": 24,
"city_id": 397,
"county_id": 2644,
"location_id": 2644,
"address": "贵州黔西南望谟县",
"start_time": 0,
"end_time": 0,
"product_amount": "8000",
"product_info": null,
"market_name": "",
"status": 3,
"supply_status": 1,
"created_time": 1591368395,
"updated_time": 1591368395,
"target_city": "[{\"city_name\":\"贵阳\",\"city_id\":392}]",
"source": 0,
"new_product_id": 8426,
"new_breed_id": 0,
"category_lv1": 65,
"category_lv2": 142
}
]
},
"sort": [
1591368395
]
},
{
"_index": "supplier",
"_type": "detail",
"_id": "896430995095174",
"_score": null,
"_source": {
"id": 189799,
"customer_id": 896430995095174,
"name": "游客3556",
"identity": "",
"summary": "",
"status": 1,
"follow_status": 1,
"created_time": 1591366312,
"updated_time": 1591366312,
"supply": null,
"staff_id": 0,
"is_assign": 0,
"next_time": 0,
"merchandiser_id": 0,
"experience": "",
"is_new": 1,
"attitude": "",
"share_id": "",
"source": 0,
"cooperation": 0,
"headpic": "",
"supply_list": [
{
"id": 195718,
"product_id": 8048,
"product_name": "荔枝",
"supplier_id": 896430995095174,
"province_id": 20,
"city_id": 338,
"county_id": 2289,
"location_id": 2289,
"address": "广东揭阳惠来县",
"start_time": 0,
"end_time": 0,
"product_amount": "每天可发一至两车9.6米车",
"product_info": null,
"market_name": "",
"status": 3,
"supply_status": 1,
"created_time": 1591366195,
"updated_time": 1591366195,
"target_city": "[]",
"source": 0,
"new_product_id": 8048,
"new_breed_id": 0,
"category_lv1": 65,
"category_lv2": 137
},
{
"id": 195720,
"product_id": 8048,
"product_name": "荔枝",
"supplier_id": 896430995095174,
"province_id": 20,
"city_id": 338,
"county_id": 2289,
"location_id": 2289,
"address": "广东揭阳惠来县",
"start_time": 0,
"end_time": 0,
"product_amount": "每天可发一9.6米长的车",
"product_info": null,
"market_name": "",
"status": 3,
"supply_status": 1,
"created_time": 1591366312,
"updated_time": 1591366312,
"target_city": "[]",
"source": 0,
"new_product_id": 8048,
"new_breed_id": 0,
"category_lv1": 65,
"category_lv2": 137
}
]
},
"sort": [
1591366312
]
}
]
}
}