【问题标题】:How to neglect fields with null value while updating Elasticsearch document?更新 Elasticsearch 文档时如何忽略具有空值的字段?
【发布时间】:2017-08-22 10:32:06
【问题描述】:

当我尝试在 elasticsearch 中更新文档而不指定某些字段时,它会将这些字段更新为 null 。这是我使用的代码。

public class DocumentModel {
@Id
private String id;
private Integer name;
private String gender;
private String url;
private String documentID;
------------------
------------------
getters and setters
}

用于索引文档的代码是:

Gson gson = new GsonBuilder().serializeNulls().create();
String json = gson.toJson(documentModel);
IndexRequest indexRequest = new IndexRequest(indexName, typeName, documentModel.getId());
indexRequest.source(json);
UpdateRequest updateRequest = new UpdateRequest(indexName, typeName, documentModel.getId());
updateRequest.doc(json);
updateRequest.upsert(indexRequest);
updateRequest.fields("documentID");
UpdateResponse updateResponse = elasticsearchTemplate.getClient().update(updateRequest).actionGet();

假设输入(documentModel)是(第一次索引文档):

{"id":1,"name":"tom","gender":"male","url":"http://www.google.com","documentID":1}

它将索引为:

{
      "_index": "index",
      "_type": "type",
      "_id": "1",
      "_score": 1,
      "_source": {
             "name":"tom",
             "gender":"male",
             "url":"http://www.google.com",
             "documentID":1
      }
    }

但是当我尝试使用输入更新同一个文档时:

{"id":1,"name":"archana","gender":"female"}

它将更新为:

{
          "_index": "index",
          "_type": "type",
          "_id": "1",
          "_score": 1,
          "_source": {
                 "name":"archana",
                 "gender":"female",
                 "url":null,
                 "documentID":null
          }
        }

问题是未作为输入给出的字段(例如'url','documentID')在更新文档时设置为null。但我希望该字段保持旧值,除非该值不为null(例如 "url":"http://www.google.com")。

【问题讨论】:

    标签: java elasticsearch


    【解决方案1】:

    我认为你的问题是serializeNullsThe docs say:

    配置 Gson 以序列化空字段。默认情况下,Gson 在序列化过程中会忽略所有为空的字段。

    我认为这意味着您正在向 Elasticsearch 发送一个类似于以下内容的请求:

    POST /index/type/1/_update
    {
      "doc": {
         "name":"archana",
         "gender":"female",
         "url":null,
         "documentID":null
      }
    }
    

    这告诉 Elasticsearch 你想用null 覆盖这些值。如果您不想覆盖它们,则需要将它们完全排除在请求之外,我认为您可以通过摆脱 serializeNulls() 调用来完成。

    这是您必须在代码或脚本更新中处理的事情(尽管我想不出您想要这样做的原因,除非您不控制发出请求的代码),或者您可以编写一个插件来添加此行为。

    【讨论】:

    • 谢谢。但是我想要 ES 中的一个选项来避免更新空值
    • 我认为这是不可能的,除非使用脚本更新(这对我来说没有多大意义),或者如果您编写并安装插件来添加此行为。也许您可以更新问题,以详细说明为什么您无法在代码中处理此问题,并且有人更有可能提出满足您需求的替代解决方案?
    【解决方案2】:

    Elastic 支持使用 _update Rest API 调用进行增量更新,所以我认为如果你这样做,Java API 也应该这样做

    updateRequest.update(indexRequest)
    

    而不是

    updateRequest.upsert(indexRequest)
    

    请注意,如果文档不存在,则显式更新将失败,因此您需要在发出更新命令之前进行检查。

    提供 Elastic 和 Java API 版本会很有用

    【讨论】:

    • 在我的情况下,如果不存在,我需要索引文档,如果在单个查询中存在则更新
    • 是的,对于特定 ID 的普通帖子会发生这种情况。但是,如果您要进行部分更新或新插入,您将必须知道文档是否存在,我认为这不能在 ElasticSearch 中的单个操作中完成。在 ES 中你永远不会真正更新文档,它们只能添加和删除,任何“更新”都会创建一个新条目并将旧条目标记为删除。是否有在发出 create 或 update 之前无法检查文档是否存在的原因?
    猜你喜欢
    • 1970-01-01
    • 2023-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-26
    • 1970-01-01
    相关资源
    最近更新 更多