Elasticsearch 8.x Java API中Update写入null值无效问题解决方法
Elasticsearch是一个广泛使用的开源分布式搜索和分析引擎,其强大的功能使得用户能够在大规模数据集上进行快速、准确的搜索、分析和可视化操作。ES适用于处理各种类型的数据,包括结构化、半结构化和非结构化数据,因此在大数据应用场景下得到了广泛的应用。
本文将详细介绍在Elasticsearch Java API中遇到的一个问题,即在进行Update操作时写入null值无效的情况,并提供了解决方案。同时,作者分享了在排查和解决问题过程中的一些经验和反思。
问题描述
在使用Elasticsearch 8.x的Java API时,根据需要可以使用以下方法来新增数据:
- Create:如果文档不存在,则创建新文档;如果文档已存在,则报错并发生异常,不会影响其他操作。
- Index:创建新文档或替换现有文档。
- Update:部分更新文档(设置upsert为true)。
然而,在大多数情况下,新增一条数据通常使用Update操作,因为我们不希望通过更新操作来覆盖整行数据。特别是在中间件同步过程中,往往需要处理多表汇聚的情况,这就需要依赖Update操作来仅更新某些字段,而不是替换整个文档。
然而,当作者使用BulkOperation构建多个Update操作时,发现将null值字段写入Elasticsearch的Index中时,该值无法正确写入。
问题排查
作者首先在Kibana控制台中进行实验,发现更新一条包含null值的文档是不可行的。这表明问题肯定存在于代码中。于是,作者将代码拆分出来进行测试。
首先,使用PUT命令将一条数据写入Elasticsearch:
PUT index_test/_doc/1 { "age": 12, "name": "John Doe" }
然后,使用Java API对_id为1的数据进行修改:
RestClient restClient = RestClient.builder(new HttpHost("xxx", 9200)).build(); ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); ElasticsearchClient client8 = new ElasticsearchClient(transport); String indexName = "index_test"; String esIdVal = "1"; Map<String, Object> doc = new HashMap<>(); doc.put("age", null); doc.put("name", null); BulkOperation op = new BulkOperation.Builder().update(i -> i.action(new UpdateAction.Builder<>() .doc(doc) .docAsUpsert(true) .build()).id(esIdVal)).build(); List<BulkOperation> list = Collections.singletonList(op); BulkResponse response = client8.bulk(builder -> builder.index(indexName).operations(list)); logger.info(response.toString()); client.shutdown();
运行结果为:
{ ... "result":"noop" ... }
返回结果中的result为noop,说明Elasticsearch实际上没有对文档进行更新操作。然而,请求的doc中携带了null值,这一现象令人困惑。作者甚至怀疑是Elasticsearch的Java API存在问题。
后来,在代码Review过程中,作者发现在初始化ElasticsearchTransport时,传入了new JacksonJsonpMapper()。通过查阅源码,作者发现JacksonJsonpMapper的默认初始化中配置了如下代码:
this(new ObjectMapper() .configure(SerializationFeature.INDENT_OUTPUT, false) .setSerializationInclusion(JsonInclude.Include.NON_NULL) );
通过观察`setSerializationInclusion(JsonInclude.Include.NON_NULL)`这一行代码,作者恍然大悟。原来是序列化器的默认配置造成了问题。默认情况下,null值会被排除在序列化的过程之外,所以导致了null值无法正确写入Elasticsearch。
因此,作者决定自定义一个ObjectMapper,并将其传递给JacksonJsonpMapper来解决这个问题。
ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper(mapper));
在修改了代码后,null值成功地被写入到Elasticsearch中。
总结
本文详细介绍了在Elasticsearch 8.x Java API中遇到的Update写入null值无效的问题,并提供了解决方案。通过自定义ObjectMapper并将其传递给JacksonJsonpMapper,我们成功地实现了将null值写入Elasticsearch的目标。同时,在使用Elasticsearch Java API时需要注意序列化器的配置,以免出现类似的问题。
反思
在本文中,作者分享了在使用Elasticsearch 8.x Java API进行Update操作时遇到的一个问题,即写入null值无效。通过对代码的排查,作者发现问题源于序列化器的默认配置。解决方案是自定义ObjectMapper并将其传递给JacksonJsonpMapper。这个问题的出现让作者反思了在使用Elasticsearch时需要对其内部实现有足够的了解,并且需要更加谨慎地进行代码审核和测试,以及更加重视配置的影响。这些反思能够帮助我们更好地使用Elasticsearch,并避免一些潜在的问题。文章来源:https://www.toymoban.com/article/616.html
关键词:Elasticsearch 8.x Java API, Update, null值, 排查, 解决文章来源地址https://www.toymoban.com/article/616.html
到此这篇关于Elasticsearch 8.x Java API中Update写入null值无效问题解决方法的文章就介绍到这了,更多相关内容可以在右上角搜索或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!