Exists Query属于Term-level Query查询, 查询某字段值不为空的文档。脑图如下:
内容说明:
本文内容同微信公众号【凡登】,关注不迷路,学习上高速,欢迎关注共同学习。原文链接:Terms-level Query之Exists Query
目录
4、mapping设置ignore_malformed演示示例
官方文档:
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/query-dsl-exists-query.html
一、语法:
1、检索字段上存在值的文档
GET /_search{
"query": {
"exists": {
"field": <field_name>
}
}
}
参数说明:
-
field : 被检索的字段
通过bool改变Exists查询方式进行反向查询,即查询字段不存在值的文档。
2、检索字段上不存在值的文档
语法:
GET /_search
{
"query": {
"bool": {
"must_not": {
"exists": {
"field": <field_name>
}
}
}
}
}
二、Exists Query示例
通过Exists Query可以查询字段值不为空的文档,那么在以下情况下
比如:
-
source中值可能为null, []
-
字段mapping参数index:false
-
字段值长度超过mapping中定义的ignore_above
-
当mapping中设置ignore_malformed,文档中字段值类型与mapping中定义的不一致
那么此时Exists Query会有什么样的表现?
0、数据准备
通过示例验证,演示数据准备如下:
DELETE exists_query_demo_index_001
// 以下样例数据经过特殊设计,用于后续检索使用,
// name字段用于验证空值
// address 字段用于验证 index:false
// content 字段用于验证ignore_above
// age 字段用于验证ignore_malformed
# 定义mapping
PUT exists_query_demo_index_001
{
"mappings": {
"properties": {
"name":{
"type":"keyword",
"fields": {
"null_value":{
"type":"keyword",
"null_value": "NULL" // 自定义空值
},
"text_value":{
"type":"text"
}
}
},
"address":{
"type":"text",
"fields": {
"keyword_value_index_false":{
"type":"keyword",
"index": false // index设置为false,即不被索引
},
"text_value_index_false":{
"type":"text",
"index": false
}
}
},
"content":{
"type":"keyword",
"ignore_above": 8 // 忽略字符长度大于8字段
},
"age":{
"type":"integer",
"ignore_malformed": true // 忽略值异常字段值
}
}
}
}
// 批量写入文档
POST exists_query_demo_index_001/_bulk?refresh=true
{"index":{"_id":1}}
{"name":"Fan","address":"BJ_1","content":"helloFan","age":17}
{"index":{"_id":2}}
{"name":"Deng","address":"BJ_2","content":"helloDeng","age":"18岁"}
{"index":{"_id":3}}
{"name":"FanDeng","address":"BJ_3","content":"helloFanDeng","age":19}
{"index":{"_id":4}}
{"name":"","address":"BJ_4","content":"hello_","age":"20岁"}
{"index":{"_id":5}}
{"name":null,"address":"BJ_5","content":"hello_null","age":21}
{"index":{"_id":6}}
{"name":"NULL","address":"BJ_6","content":"hello_NULL","age":22}
{"index":{"_id":7}}
{"name":[],"address":"BJ_7","content":"hello_[]","age":"23岁"}
{"index":{"_id":8}}
{"name":[""],"address":"BJ_8","content":"hello_[empty_char]","age":24}
{"index":{"_id":9}}
{"name":[null],"address":"BJ_9","content":"hello_[null]","age":25}
{"index":{"_id":10}}
{"name":["NULL"],"address":"BJ_10","content":"hello_[NULL]","age":26}
{"index":{"_id":11}}
{"name":["","Fan"],"address":"BJ_11","content":"hello_[empty_char,Fan]","age":27}
{"index":{"_id":12}}
{"name":[null,"Fan"],"address":"BJ_12","content":"hello_[null,Fan]","age":28}
{"index":{"_id":13}}
{"name":["NULL","Fan"],"address":"BJ_13","content":"hello_[NULL,Fan]","age":29}
//查询数据是否写入
GET exists_query_demo_index_001/_search
{
"track_total_hits": true, // 显示检索数据的记录数
"size": 0 // 不显示source
}
结果:
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 13, // 13条数据全部写入
"relation" : "eq" //
},
"max_score" : null,
"hits" : [ ]
}
}
1、当字段值为空的演示示例:
GET exists_query_demo_index_001/_search
{
"track_total_hits": true,
"size": 20,
"query": {
"exists": {
"field": "name"
}
}
}
结果显示:id为5,7,9的文档name不存在值
即当字段值为null, 空数组[]或[null] 的时候,Exists Query检索不到相关文档
以下query检查与上述查询结果相通
GET exists_query_demo_index_001/_search
{
"track_total_hits": true,
"size": 20,
"query": {
"exists": {
"field": "name.text_value"
}
}
}
即类型为keyword以及text的字段,Exists Query查询结果相同
我们通过反向查询看看字段name不存在值的文档有哪些
GET exists_query_demo_index_001/_search
{
"track_total_hits": true,
"query": {
"bool": {
"must_not": [
{
"exists": {
"field": "name"
}
}
]
}
}
}
结果:
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 0.0,
"hits" : [
{
"_index" : "exists_query_demo_index_001",
"_type" : "_doc",
"_id" : "5",
"_score" : 0.0,
"_source" : {
"name" : null,
"address" : "BJ_5",
"content" : "hello_null",
"age" : 21
}
},
{
"_index" : "exists_query_demo_index_001",
"_type" : "_doc",
"_id" : "7",
"_score" : 0.0,
"_ignored" : [
"age"
],
"_source" : {
"name" : [ ],
"address" : "BJ_7",
"content" : "hello_[]",
"age" : "23岁"
}
},
{
"_index" : "exists_query_demo_index_001",
"_type" : "_doc",
"_id" : "9",
"_score" : 0.0,
"_source" : {
"name" : [
null
],
"address" : "BJ_9",
"content" : "hello_[null]",
"age" : 25
}
}
]
}
}
GET exists_query_demo_index_001/_search
{
"track_total_hits": true,
"size": 20,
"query": {
"exists": {
"field": "name.null_value"
}
}
}
结果显示:id为7的文档name不存在值
即当字段值为 空数组[] 的时候,Exists Query检索不到相关文档
字段name.null_value为自定义空值,当字段值出现空值的时候会填充自定义的默认值,故当检查到null 实际填充值为 NULL
小结:
即当字段值为null, 空数组[]或[null] 的时候,Exists Query检索不到相关文档,
如果自定义了空值,那么仅字段值空数组[]下,Exists Query检索不到相关文档
2、当index:false情况下 演示示例
GET exists_query_demo_index_001/_search
{
"size": 20,
"query": {
"exists": {
"field": "address"
}
}
}
结果:所有文档的address字段均存在值,
GET exists_query_demo_index_001/_search
{
"size": 20,
"query": {
"exists": {
"field": "address.keyword_index_false"
}
}
}
结果:所有文档的address字段均不存在值,
GET exists_query_demo_index_001/_search
{
"size": 20,
"query": {
"exists": {
"field": "address.text_index_false"
}
}
}
结果:所有文档的address字段均不存在值,
小结:当index:false时,所有文档的address字段均不存在值,Exists Query检索不到相关文档
3、mapping设置ignore_above演示示例
GET exists_query_demo_index_001/_search
{
"size": 20,
"query": {
"exists": {
"field": "content"
}
}
}
结果:
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "exists_query_demo_index_001",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"name" : "Fan",
"address" : "BJ_1",
"content" : "helloFan",
"age" : 17
}
},
{
"_index" : "exists_query_demo_index_001",
"_type" : "_doc",
"_id" : "4",
"_score" : 1.0,
"_ignored" : [
"age"
],
"_source" : {
"name" : "",
"address" : "BJ_4",
"content" : "hello_",
"age" : "20岁"
}
},
{
"_index" : "exists_query_demo_index_001",
"_type" : "_doc",
"_id" : "7",
"_score" : 1.0,
"_ignored" : [
"age"
],
"_source" : {
"name" : [ ],
"address" : "BJ_7",
"content" : "hello_[]",
"age" : "23岁"
}
}
]
}
}
小结:
当字段值超过ignore_above配置的长度时,Exists Query检索不到相关文档
4、mapping设置ignore_malformed演示示例
GET exists_query_demo_index_001/_search
{
"size": 20,
"query": {
"exists": {
"field": "age"
}
}
}
通过反向查询看看有哪些age字段不存在值的文档
GET exists_query_demo_index_001/_search
{
"track_total_hits": true,
"query": {
"bool": {
"must_not": [
{
"exists": {
"field": "age"
}
}
]
}
}
}
结果:
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 0.0,
"hits" : [
{
"_index" : "exists_query_demo_index_001",
"_type" : "_doc",
"_id" : "2",
"_score" : 0.0,
"_ignored" : [
"age"
],
"_source" : {
"name" : "Deng",
"address" : "BJ_2",
"content" : "helloDeng",
"age" : "18岁"
}
},
{
"_index" : "exists_query_demo_index_001",
"_type" : "_doc",
"_id" : "4",
"_score" : 0.0,
"_ignored" : [
"age"
],
"_source" : {
"name" : "",
"address" : "BJ_4",
"content" : "hello_",
"age" : "20岁"
}
},
{
"_index" : "exists_query_demo_index_001",
"_type" : "_doc",
"_id" : "7",
"_score" : 0.0,
"_ignored" : [
"age"
],
"_source" : {
"name" : [ ],
"address" : "BJ_7",
"content" : "hello_[]",
"age" : "23岁"
}
}
]
}
}
小结:
当ignore_malformed配置时,字段值类型与mapping中字段类型不一致或一些不符合要求的字段值,Exists Query检索不到相关文档
三、总结:
针对Exists Query检索,以下4种情况会出现Exists Query检索不到相关文档
-
1、当检索字段值为null, 空数组[], [null], Exists Query检索不到相关文档。存在自定义空值则除外
-
2、当index:false时,所有文档的address字段均不存在值,Exists Query检索不到相关文档
-
3、当字段值超过ignore_above配置的长度时,Exists Query检索不到相关文档
-
4、当ignore_malformed配置时,字段值类型与mapping中字段类型不一致或一些不符合要求的字段值,Exists Query检索不到相关文档