Exists Query属于Term-level Query查询, 查询某字段值不为空的文档。脑图如下:
内容说明:
本文内容同微信公众号【凡登】,关注不迷路,欢迎加入一起共同学习。原文链接:Terms-level Query之Exists Query
目录
一、语法:
1、检索字段上存在值的文档
2、检索字段上不存在值的文档
二、Exists Query示例
0、数据准备
1、当字段值为空的演示示例:
2、当index:false情况下 演示示例
3、mapping设置ignore_above演示示例
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": } }}
GET /_search{ "query": { "exists": { "field": } }}
参数说明:
-
field : 被检索的字段
通过bool改变Exists查询方式进行反向查询,即查询字段不存在值的文档。
2、检索字段上不存在值的文档
语法:
GET /_search{ "query": { "bool": { "must_not": { "exists": { "field": } } } }}
二、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# 定义mappingPUT 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检索不到相关文档



