Elasticsearch 空值处理实战指南

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 1、引言实战业务场景中,经常会遇到定义空值、检索指定空值数据的情况。这时候,当我们翻看官方文档 null_value 部分,会看到如下的描述:Accepts a string value which is substituted for any explicit null values. Defaults to null, which means the field is treated as missing.接受一个字符串值替换所有显式的空值。默认为null,这意味着该字段被视为丢失。A null value cannot be indexed or searched. W

好吧,死磕一把,探个究竟:


DELETE my-index-000001

PUT my-index-000001

{

 "mappings": {

   "properties": {

     "status_code": {

       "type": "keyword"

     },

     "title": {

       "type": "text"

     }

   }

 }

}

PUT my-index-000001/_bulk

{"index":{"_id":1}}

{"status_code":null,"title":"just test"}

{"index":{"_id":2}}

{"status_code":"","title":"just test"}

{"index":{"_id":3}}

{"status_code":[],"title":"just test"}

POST my-index-000001/_search

POST my-index-000001/_search

{

 "query": {

   "term": {

     "status_code": null

   }

 }

}

如上检索返回错误如下:


{

 "error": {

   "root_cause": [

     {

       "type": "illegal_argument_exception",

       "reason": "field name is null or empty"

     }

   ],

   "type": "illegal_argument_exception",

   "reason": "field name is null or empty"

 },

 "status": 400

}

2、null_value 的含义

The null_value parameter allows you to replace explicit null values with the specified value so that it can be indexed and searched.


使用 null_value 参数可以用指定的值替换显式的空值,以便可以对其进行索引和搜索。例如:


DELETE my-index-000001

PUT my-index-000001

{

 "mappings": {

   "properties": {

     "status_code": {

       "type":       "keyword",

       "null_value": "NULL"

     }

   }

 }

}

PUT my-index-000001/_bulk

{"index":{"_id":1}}

{"status_code":null}

{"index":{"_id":2}}

{"status_code":[]}

{"index":{"_id":3}}

{"status_code":"NULL"}

GET my-index-000001/_search

{

 "query": {

   "term": {

     "status_code": "NULL"

   }

 }

}

注意,这里返回结果:包含 _id  = 1 以及 _id =3 的文档,不包含_id = 2 的文档。


说明一下:


"null_value": "NULL" 的含义:用指定的值替换显式的空值,“NULL”可以自定义,比如业务系统中我们可以定义成“Unkown”。


大家能看懂的大白话解释如下:


相当于我们在 Mapping 定义阶段指定了空的默认值,用“NULL”来代替,这样做的好处:类似如上的_id = 1 的文档,空字段也可以被索引、检索。


不会再报 "field name is null or empty" 的错误了。


3、null_value 使用注意

null_value 必须和定义的数据类型匹配,举例:long 类型字段不能有string 类型的 null value。


如下的定义就会报错:


PUT my-index-000001

{

 "mappings": {

   "properties": {

     "status_code": {

       "type": "keyword"

     },

     "title": {

       "type": "long",

       "null_value": "NULL"

     }

   }

 }

}

报错如下:


{

 "error": {

   "root_cause": [

     {

       "type": "mapper_parsing_exception",

       "reason": "Failed to parse mapping [_doc]: For input string: \"NULL\""

     }

   ],

   "type": "mapper_parsing_exception",

   "reason": "Failed to parse mapping [_doc]: For input string: \"NULL\"",

   "caused_by": {

     "type": "number_format_exception",

     "reason": "For input string: \"NULL\""

   }

 },

 "status": 400

}

解释一下:明显类型不匹配导致。


null_value 只影响了数据的索引,不会修改_source 文档。


4、哪些字段有null_value, 哪些字段没有null_value?

以下核心的常用字段都支持:null_value。


Arrays


Boolean


Date


geo_point


IP


Keyword


Numeric


point


别问我怎么知道的,挨个翻查的官方文档确认的。


最核心常问到的问题:


4.1 问题1:text 类型不支持 null_value 吗?

是的,不支持。


来吧,实战一把:


DELETE my-index-000001

PUT my-index-000001

{

 "mappings": {

   "properties": {

     "status_code": {

       "type": "keyword"

     },

     "title": {

       "type": "text",

       "null_value": "NULL"

     }

   }

 }

}

返回结果如下:


{

 "error": {

   "root_cause": [

     {

       "type": "mapper_parsing_exception",

       "reason": "Mapping definition for [title] has unsupported parameters:  [null_value : NULL]"

     }

   ],

   "type": "mapper_parsing_exception",

   "reason": "Failed to parse mapping [_doc]: Mapping definition for [title] has unsupported parameters:  [null_value : NULL]",

   "caused_by": {

     "type": "mapper_parsing_exception",

     "reason": "Mapping definition for [title] has unsupported parameters:  [null_value : NULL]"

   }

 },

 "status": 400

}

问题2:如果 text 类型也想设置空值,怎么搞呢?

推荐 multi-fields,借助 keyword 和 text 组合达到业务需求。


定义参考如下:


PUT my-index-000001

{

 "mappings": {

   "properties": {

     "status_code": {

       "type": "keyword"

     },

     "title": {

       "type": "text",

       "fields": {

         "keyword": {

           "type": "keyword",

           "null_value": "NULL"

         }

       }

     }

   }

 }

}

对于 text 类型的字段,实战业务场景下,我们经常会需要同时设置:multi_fields, 将 text 和 keyword 组合设置。


text 类型用于全文检索,keyword用于聚合和排序。


同时,multi_fields 是 Elastic 认证工程师的核心考点之一,大家务必要掌握。


5、线上问题探讨

老哥们,请教一个问题 ,我现在数据中有content这个字段,我想查询这个字段不为空字符串,我用must_not不行。我贴下我的sql


死磕 Elasticsearch 技术交流群

image.png

我的解读如下:


说下这个问题正确写法,以及之前写法不对的原因。


判定是否为空,本质是:精准匹配问题,不是全文检索的范畴(相似度匹配),所以选型使用:match_phrase 导致后面的错误。应该使用:term。


POST test_001/_search

{

 "query": {

   "bool": {

     "filter": {

       "bool": {

         "must": [

           {

             "exists": {

               "field": "cont"

             }

           },

           {

             "term": {

               "content.keyword": {

                 "value": ""

               }

             }

           }

         ]

       }

     }

   }

 }

}

注意:exists 检索的含义是判定字段是否存在,结合使用效果佳、更稳妥!


如下的脚本也可以实现,但由于性能问题,实际业务层面不推荐使用。


POST test_001/_search

{

 "query": {

   "bool": {

     "filter": {

       "script": {

         "script": {

           "source": "doc['content.keyword'].length == 1",

           "lang": "painless"

         }

       }

     }

   }

 }

}

试想一下,如果在定义 Mapping 的数据建模阶段就定义了 text 和 keyword的组合 fields,并且:为keyword 设置了 null_value,这个问题就更好解决了。


6、小结正如罗胖所说:再显而易见的道理,在中国至少有一亿人不知道。


而,我认为 Elasticsearch 技术也是,再显而易见的技术点,在中国 Elastic 技术圈,至少有 N 多人不知道。


怎么办?死磕一下,探个究竟吧!


你的业务场景怎么处理空值的呢?欢迎留言讨论。


7、加餐-讨论

有读者私信留言:


其实老大也可以学习一下其他号,转载一些大 V 或大公司的流量文章,图文并茂的,虽然大家不一定看得懂,但看上去就很牛逼的样子,给你的公号也能增粉,多好啊!你一周才1篇文章,大家都走了。


我的回复:


每个公众号都有自己的使命和存在的价值,你可以仔细对比,每个号主都有自己的特点,为什么要趋同呢?我感觉这样也很好(就是苦点、穷点),并且从长远角度(十年甚至更长时间),坚持原创的价值才能体现。


加微信:elastic6(仅有少量坑位了),和 BAT 大佬一起精进 Elastic 技术!

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
1月前
|
存储 运维 监控
超越传统模型:从零开始构建高效的日志分析平台——基于Elasticsearch的实战指南
【10月更文挑战第8天】随着互联网应用和微服务架构的普及,系统产生的日志数据量日益增长。有效地收集、存储、检索和分析这些日志对于监控系统健康状态、快速定位问题以及优化性能至关重要。Elasticsearch 作为一种分布式的搜索和分析引擎,以其强大的全文检索能力和实时数据分析能力成为日志处理的理想选择。
103 6
|
4月前
|
存储 数据采集 数据处理
数据处理神器Elasticsearch_Pipeline:原理、配置与实战指南
数据处理神器Elasticsearch_Pipeline:原理、配置与实战指南
175 12
|
5月前
|
SQL 安全 数据挖掘
Elasticsearch如何聚合查询多个统计值,如何嵌套聚合?并相互引用,统计索引中某一个字段的空值率?语法是怎么样的?
Elasticsearch聚合查询用于复杂数据分析,包括统计空值率。示例展示了如何计算字段`my_field`非空非零文档的百分比。查询分为三步:总文档数计数、符合条件文档数计数及计算百分比。聚合概念涵盖度量、桶和管道聚合。脚本在聚合中用于动态计算。常见聚合类型如`sum`、`avg`、`date_histogram`等。组合使用可实现多值统计、嵌套聚合和空值率计算。[阅读更多](https://zhangfeidezhu.com/?p=515)
297 0
Elasticsearch如何聚合查询多个统计值,如何嵌套聚合?并相互引用,统计索引中某一个字段的空值率?语法是怎么样的?
|
5月前
|
缓存 数据处理 数据安全/隐私保护
Elasticsearch索引状态管理实战指南
Elasticsearch索引状态管理实战指南
|
5月前
|
存储 索引
Elasticsearch索引之嵌套类型:深度剖析与实战应用
Elasticsearch索引之嵌套类型:深度剖析与实战应用
|
6月前
|
人工智能 自然语言处理 开发者
Langchain 与 Elasticsearch:创新数据检索的融合实战
Langchain 与 Elasticsearch:创新数据检索的融合实战
189 10
|
5月前
|
存储 JSON 搜索推荐
Springboot2.x整合ElasticSearch7.x实战(三)
Springboot2.x整合ElasticSearch7.x实战(三)
47 0
|
5月前
|
存储 自然语言处理 关系型数据库
Springboot2.x整合ElasticSearch7.x实战(二)
Springboot2.x整合ElasticSearch7.x实战(二)
49 0
|
5月前
|
搜索推荐 数据可视化 Java
Springboot2.x整合ElasticSearch7.x实战(一)
Springboot2.x整合ElasticSearch7.x实战(一)
47 0
|
6月前
|
存储 缓存 监控
干货 | Elasticsearch 8.X 性能优化实战
干货 | Elasticsearch 8.X 性能优化实战
592 2