Python操作ES判断字段是否存在的一个问题
ES与sdk的版本
""" ES版本: 7.16.2 Python SDK版本: elasticsearch 7.17.9 elasticsearch-dsl 7.4.0 """
代码说明
使用下面方法查询:
s = self.search(index) # 查询 _id 等于 doc_id 且字段 field_name 存在 s = s.query("bool", must={"exists": {"field": field_name}}, filter=[Q('term', _id=doc_id)]) res = s.execute()
实际查询的ES的query语句:
{ "query": { "bool": { "must": [ { "exists": { "field": "other" } } ], "filter": [ { "term": { "_id": "1" } } ] } } }
1、只判断字段是否存在于某个doc中(下面的check_doc_field_exists方法)
实测: 如果字段对应的值是 null、空列表[]、空字典{} 会返回False, 但是列表里有数据会返回True
如果字段对应的值是 0、空字符串、false 会返回True
2、查询的字段为空字符串的话是能查到数据的,所以实际需求中如果空字符串不是合理的数据的话需要额外写逻辑判断,如下面的check_doc_exists_and_not_blank_str方法
from elasticsearch import Elasticsearch from elasticsearch_dsl import Search, Q """ ES版本: 7.16.2 Python SDK版本: elasticsearch 7.17.9 elasticsearch-dsl 7.4.0 """ class ESClient: def __init__(self, hosts): """ 初始化 Elasticsearch 客户端 """ self.client = Elasticsearch(hosts=hosts) def search(self, index): """ 创建一个 Search 对象 """ return Search(using=self.client, index=index) def check_doc_field_exists(self, index, doc_id, field_name): """ 检查 ES 文档的字段是否存在 Notice 只判断字段是否存在于某个doc中 Notice 实测: 如果字段对应的值是 null、空列表[]、空字典{} 会返回False, 但是列表里有数据会返回True Notice 如果字段对应的值是 0、空字符串、false 会返回True """ s = self.search(index) # 查询 _id 等于 doc_id 且字段 field_name 存在 s = s.query("bool", must={"exists": {"field": field_name}}, filter=[Q('term', _id=doc_id)]) res = s.execute() print("check_doc_field_exists 实际查询的语句:>> ", s.to_dict()) print("check_doc_field_exists res.hits:>> ", type(res.hits), ";", res.hits) # 如果查询结果非空,说明文档存在且字段存在 return len(res.hits) > 0 def check_doc_exists_and_not_blank_str(self, index, doc_id, field_name): """ 检查 ES 文档的字段是否存在,并且值不为空字符串 Notice 判断字段是否存在于某个doc中,并且值不为空字符串 """ s = self.search(index) # 查询 _id 等于 doc_id 且字段 field_name 存在 s = s.query("bool", must={"exists": {"field": field_name}}, filter=[Q('term', _id=doc_id)]) res = s.execute() print("check_doc_exists_and_not_blank_str res:>> ", type(res.hits), ";", res.hits) if not res.hits: # 没有匹配到文档,返回 False return False # 获取文档内容 doc = res.hits[0].to_dict() # 检查字段是否存在,并判断是否为 None 或空列表 field_value = doc.get(field_name) if field_value is None or field_value == "": return False return True if __name__ == "__main__": es_hosts = ["http://localhost:9200"] es_client = ESClient(es_hosts) index_name = "student" document_id = "1" field_to_check = "other" exists1 = es_client.check_doc_field_exists(index_name, document_id, field_to_check) print(f"字段是否存在: {exists1}") exists2 = es_client.check_doc_exists_and_not_blank_str(index_name, document_id, field_to_check) print(f"字段是否存在且不为空字符串: {exists2}") # 实际查询的语句 """ { "query": { "bool": { "must": [ { "exists": { "field": "other" } } ], "filter": [ { "term": { "_id": "1" } } ] } } } """
~~~