ES 判断某个字段值不为空,怎么写?
在 Elasticsearch 中,判断某个字段值不为空有以下几种常用写法:
1. 使用 exists 查询(推荐)
{
"query": {
"bool": {
"must": [
{
"exists": {
"field": "your_field_name"
}
}
]
}
}
}
2. 使用 bool 查询组合
{
"query": {
"bool": {
"must": [
{
"exists": {
"field": "your_field_name"
}
}
],
"must_not": [
{
"term": {
"your_field_name": ""
}
}
]
}
}
}
3. 针对不同数据类型的完整判断
{
"query": {
"bool": {
"must": [
{
"exists": {
"field": "your_field_name"
}
}
],
"must_not": [
{
"term": {
"your_field_name": ""
}
},
{
"term": {
"your_field_name": null
}
}
]
}
}
}
4. 在 filter context 中使用
{
"query": {
"bool": {
"filter": [
{
"exists": {
"field": "your_field_name"
}
}
]
}
}
}
5. 使用 script 查询(更灵活但性能较差)
{
"query": {
"bool": {
"filter": {
"script": {
"script": {
"source": "doc['your_field_name'].size() > 0 && doc['your_field_name'].value != null && doc['your_field_name'].value != ''"
}
}
}
}
}
}
实际使用示例
假设字段名为 title:
GET /your_index/_search
{
"query": {
"bool": {
"must": [
{
"exists": {
"field": "title"
}
}
],
"must_not": [
{
"term": {
"title": ""
}
}
]
}
}
}
注意事项
- exists 查询:检查字段是否存在且不为 null
- 空字符串判断:需要额外使用 term 查询排除空字符串
- 性能考虑:exists 查询性能最好,script 查询最差
- 嵌套字段:对于嵌套对象,需要使用 nested 查询结合 exists
推荐使用第一种或第二种方法,根据具体需求选择。
"error" : { "root_cause" : [ { "type" : "x_content_parse_exception", "reason" : "[32:11] [bool] failed to parse field [must_not]" } ], "type" : "x_content_parse_exception", "reason" : "[32:11] [bool] failed to parse field [must_not]", "caused_by" : { "type" : "illegal_argument_exception", "reason" : "value cannot be null" } }, "status" : 400 }
这个错误是因为在 must_not 子句中使用了 null 值。在 Elasticsearch 中,term 查询不能直接使用 null 作为值。
正确的写法:
方法1:简化版(推荐)
{
"query": {
"bool": {
"must": [
{
"exists": {
"field": "your_field_name"
}
}
],
"must_not": [
{
"term": {
"your_field_name": ""
}
}
]
}
}
}
方法2:如果只需要检查字段存在(不检查空字符串)
{
"query": {
"exists": {
"field": "your_field_name"
}
}
}
方法3:使用 range 查询检查字段长度(针对字符串字段)
{
"query": {
"bool": {
"must": [
{
"exists": {
"field": "your_field_name"
}
},
{
"range": {
"your_field_name.length": {
"gt": 0
}
}
}
]
}
}
}
方法4:使用 script 查询(处理复杂情况)
{
"query": {
"script": {
"script": {
"source": "doc.containsKey('your_field_name') && doc['your_field_name'].size() > 0 && doc['your_field_name'].value != null && doc['your_field_name'].value != ''"
}
}
}
}
错误原因分析:
你之前的查询中可能包含了类似这样的部分:
{
"term": {
"your_field_name": null // ❌ 这是不允许的
}
}
实际示例:
假设要查询 title 字段不为空的文档:
GET /your_index/_search
{
"query": {
"bool": {
"must": [
{
"exists": {
"field": "title"
}
}
],
"must_not": [
{
"term": {
"title": ""
}
}
]
}
}
}
推荐使用方法1,它既检查字段存在,又排除空字符串,是最常用的方式。
字段不是字符串,是date类型
对于 date 类型的字段,判断不为空的写法会更简单,因为 date 类型不会有空字符串的问题。
正确的写法:
方法1:使用 exists 查询(推荐)
{
"query": {
"exists": {
"field": "your_date_field"
}
}
}
方法2:在 bool 查询中使用
{
"query": {
"bool": {
"must": [
{
"exists": {
"field": "your_date_field"
}
}
]
}
}
}
方法3:使用 range 查询检查日期范围
{
"query": {
"bool": {
"must": [
{
"exists": {
"field": "your_date_field"
}
},
{
"range": {
"your_date_field": {
"gte": "1970-01-01"
}
}
}
]
}
}
}
方法4:使用 script 查询(如果需要更复杂的逻辑)
{
"query": {
"script": {
"script": {
"source": "doc.containsKey('your_date_field') && doc['your_date_field'].size() > 0"
}
}
}
}
实际示例:
假设有一个 create_time 字段是 date 类型:
GET /your_index/_search
{
"query": {
"exists": {
"field": "create_time"
}
}
}
针对 date 字段的特殊说明:
date 类型特点:
- 不会有空字符串问题
- 如果字段值为 null 或不存在,exists 查询会自动排除
- 有效的日期值都会被认为是"非空"
推荐使用最简单的方式:
JSON{ "query": { "exists": { "field": "your_date_field" } } }如果需要排除特定日期(如 1970-01-01):
JSON{ "query": { "bool": { "must": [ { "exists": { "field": "create_time" } } ], "must_not": [ { "term": { "create_time": "1970-01-01T00:00:00.000Z" } } ] } } }
最简单的推荐写法就是方法1,使用 exists 查询即可满足 date 字段不为空的判断需求。
exists 已经排查字段不存在和存在但是为null的情况了吗?
是的,exists 查询已经同时排除了字段不存在和字段值为 null 的情况。
exists 查询的作用范围:
1. 会排除的情况:
- 字段不存在的文档
- 字段存在但值为
null的文档 - 字段存在但值为空数组
[]的文档
2. 会包含的情况:
- 字段有任何非 null 值的文档
- 包括:空字符串
""、0、false、空对象{}等
验证示例:
假设有以下文档:
[
{ "id": 1, "date_field": "2023-01-01" }, // ✅ 会被 exists 匹配
{ "id": 2, "date_field": null }, // ❌ 不会被匹配(null)
{ "id": 3 }, // ❌ 不会被匹配(字段不存在)
{ "id": 4, "date_field": "" }, // ✅ 会被匹配(空字符串,但 date 类型不会有这种情况)
{ "id": 5, "date_field": 0 } // ✅ 会被匹配(但 date 类型不会有数字0)
]
对于 date 类型的特别说明:
由于 date 类型字段:
- 不会有空字符串
""的问题 - 不会有数字
0的问题 - 有效的日期值都是非 null
因此对于 date 字段,简单的 exists 查询就完全足够了:
{
"query": {
"exists": {
"field": "your_date_field"
}
}
}
这个查询会精确地返回所有 your_date_field 字段存在且具有有效日期值的文档。
总结:
✅ 对于 date 类型字段,exists 查询已经完美覆盖了"不为空"的所有情况,包括排除字段不存在和 null 值的情况。