ES查询字段值不为空的多种写法

小豆丁 3天前 ⋅ 12 阅读
聊天记录
头像

ES 判断某个字段值不为空,怎么写?

头像

在 Elasticsearch 中,判断某个字段值不为空有以下几种常用写法:

1. 使用 exists 查询(推荐)

JSON
{
  "query": {
    "bool": {
      "must": [
        {
          "exists": {
            "field": "your_field_name"
          }
        }
      ]
    }
  }
}

2. 使用 bool 查询组合

JSON
{
  "query": {
    "bool": {
      "must": [
        {
          "exists": {
            "field": "your_field_name"
          }
        }
      ],
      "must_not": [
        {
          "term": {
            "your_field_name": ""
          }
        }
      ]
    }
  }
}

3. 针对不同数据类型的完整判断

JSON
{
  "query": {
    "bool": {
      "must": [
        {
          "exists": {
            "field": "your_field_name"
          }
        }
      ],
      "must_not": [
        {
          "term": {
            "your_field_name": ""
          }
        },
        {
          "term": {
            "your_field_name": null
          }
        }
      ]
    }
  }
}

4. 在 filter context 中使用

JSON
{
  "query": {
    "bool": {
      "filter": [
        {
          "exists": {
            "field": "your_field_name"
          }
        }
      ]
    }
  }
}

5. 使用 script 查询(更灵活但性能较差)

JSON
{
  "query": {
    "bool": {
      "filter": {
        "script": {
          "script": {
            "source": "doc['your_field_name'].size() > 0 && doc['your_field_name'].value != null && doc['your_field_name'].value != ''"
          }
        }
      }
    }
  }
}

实际使用示例

假设字段名为 title

JSON
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:简化版(推荐)

JSON
{
  "query": {
    "bool": {
      "must": [
        {
          "exists": {
            "field": "your_field_name"
          }
        }
      ],
      "must_not": [
        {
          "term": {
            "your_field_name": ""
          }
        }
      ]
    }
  }
}

方法2:如果只需要检查字段存在(不检查空字符串)

JSON
{
  "query": {
    "exists": {
      "field": "your_field_name"
    }
  }
}

方法3:使用 range 查询检查字段长度(针对字符串字段)

JSON
{
  "query": {
    "bool": {
      "must": [
        {
          "exists": {
            "field": "your_field_name"
          }
        },
        {
          "range": {
            "your_field_name.length": {
              "gt": 0
            }
          }
        }
      ]
    }
  }
}

方法4:使用 script 查询(处理复杂情况)

JSON
{
  "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 != ''"
      }
    }
  }
}

错误原因分析:

你之前的查询中可能包含了类似这样的部分:

JSON
{
  "term": {
    "your_field_name": null  // ❌ 这是不允许的
  }
}

实际示例:

假设要查询 title 字段不为空的文档:

JSON
GET /your_index/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "exists": {
            "field": "title"
          }
        }
      ],
      "must_not": [
        {
          "term": {
            "title": ""
          }
        }
      ]
    }
  }
}

推荐使用方法1,它既检查字段存在,又排除空字符串,是最常用的方式。

头像

字段不是字符串,是date类型

头像

对于 date 类型的字段,判断不为空的写法会更简单,因为 date 类型不会有空字符串的问题。

正确的写法:

方法1:使用 exists 查询(推荐)

JSON
{
  "query": {
    "exists": {
      "field": "your_date_field"
    }
  }
}

方法2:在 bool 查询中使用

JSON
{
  "query": {
    "bool": {
      "must": [
        {
          "exists": {
            "field": "your_date_field"
          }
        }
      ]
    }
  }
}

方法3:使用 range 查询检查日期范围

JSON
{
  "query": {
    "bool": {
      "must": [
        {
          "exists": {
            "field": "your_date_field"
          }
        },
        {
          "range": {
            "your_date_field": {
              "gte": "1970-01-01"
            }
          }
        }
      ]
    }
  }
}

方法4:使用 script 查询(如果需要更复杂的逻辑)

JSON
{
  "query": {
    "script": {
      "script": {
        "source": "doc.containsKey('your_date_field') && doc['your_date_field'].size() > 0"
      }
    }
  }
}

实际示例:

假设有一个 create_time 字段是 date 类型:

JSON
GET /your_index/_search
{
  "query": {
    "exists": {
      "field": "create_time"
    }
  }
}

针对 date 字段的特殊说明:

  1. date 类型特点

    • 不会有空字符串问题
    • 如果字段值为 null 或不存在,exists 查询会自动排除
    • 有效的日期值都会被认为是"非空"
  2. 推荐使用最简单的方式

    JSON
    {
      "query": {
        "exists": {
          "field": "your_date_field"
        }
      }
    }
    
  3. 如果需要排除特定日期(如 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 值的文档
  • 包括:空字符串 ""0false、空对象 {}

验证示例:

假设有以下文档:

JSON
[
  { "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 查询就完全足够了

JSON
{
  "query": {
    "exists": {
      "field": "your_date_field"
    }
  }
}

这个查询会精确地返回所有 your_date_field 字段存在且具有有效日期值的文档。

总结:

对于 date 类型字段,exists 查询已经完美覆盖了"不为空"的所有情况,包括排除字段不存在和 null 值的情况。

全部评论: 0

    我有话说: