ElasticsearchRepository跳过空值

问题描述

我有Repo与ES索引进行交互:

@Repository
public interface RegDocumentRepo extends ElasticsearchRepository<RegDocument,String> {
}

RegDocument类是reg-document索引的POJO:

@Document(indexName = "reg-document")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RegDocument {

    @Id
    String id;

    @Field(type = FieldType.Nested,includeInParent = true)
    private List<Map<String,Object>> attachments;

    private String author;

    @Field(type = FieldType.Nested,Object>> classification;

    private String content;

    private String intent;

    @Field(type = FieldType.Nested,Object>> links;

    private String name;

    @Field(name = "publication_date")
    private String publicationDate;

    private Integer raiting;
    private Long status;
    private String title;
    private String type;
    private String version;
}

要隐藏我的业务逻辑,我可以使用服务:

@RequiredArgsConstructor
@Service
public class SearchServiceImpl {

    @Autowired
    RegDocumentRepo regDocumentRepo;

    public RegDocument updateRating(String uuid,Integer rating) throws IOException {
        final RegDocument regDocument = regDocumentRepo
                                            .findById(uuid)
                                            .orElseThrow(() -> new IOException(String.format("No document with %s id",uuid)));
        Integer ratingFromDB = regDocument.getRaiting();
        ratingFromDB = ratingFromDB == null ? rating : ratingFromDB + rating;

        regDocument.setRaiting(ratingFromDB);

        final RegDocument save = regDocumentRepo.save(regDocument);

        return save;
    }

}

所以我的ES索引中有这样的文档:

{
    "_index" : "reg-document","_type" : "_doc","_id" : "9wEgQnQBKzq7IqBZMDaO","_score" : 1.0,"_source" : {
      "raiting" : null,"attachments" : null,"author" : null,"type" : "answer","classification" : [
        {
          "code" : null,"level" : null,"name" : null,"description" : null,"id_parent" : null,"topic_type" : null,"uuid" : null
        }
      ],"intent" : null,"version" : null,"content" : "В 2019 году размер материнского капитала составляет 453026 рублей","name" : "Каков размер МСК в 2019 году?","publication_date" : "2020-08-26 06:49:10","rowkey" : null,"links" : null,"status" : 1
    }
  }

但是,在更新排名分数之后,我有了下一个结构:

{
    "_index" : "reg-document","_source" : {
      "raiting" : 4,"status" : 1
    }
  }

如您所见,Java服务会跳过NULL值。但是,如果该字段是嵌套字段,则将保存空值。

ElasticSearch版本-7.8.0

spring数据的maven依赖项:

<dependency>
   <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-elasticsearch</artifactId>
    <version>4.0.0.RELEASE</version>
</dependency>

那么我如何保存空值,而不跳过它们?

**

UDP

**

我已经研究了spring-data-elasticsearch-4.0.0的依赖性,并发现,正如最佳答案作者所说的,MappingElasticsearchConverter.java具有以下方法:

@Override
public void write(Object source,Document sink) {

    Assert.notNull(source,"source to map must not be null");

    if (source instanceof Map) {
        // noinspection unchecked
        sink.putAll((Map<String,Object>) source);
        return;
    }

    Class<?> entityType = ClassUtils.getUserClass(source.getClass());
    TypeInformation<?> type = ClassTypeInformation.from(entityType);

    if (requiresTypeHint(type,source.getClass(),null)) {
        typeMapper.writeType(source.getClass(),sink);
    }

    Optional<Class<?>> customTarget = conversions.getCustomWriteTarget(entityType,Map.class);

    if (customTarget.isPresent()) {
        sink.putAll(conversionService.convert(source,Map.class));
        return;
    }

    ElasticsearchPersistentEntity<?> entity = type.getType().equals(entityType)
            ? mappingContext.getRequiredPersistentEntity(type)
            : mappingContext.getRequiredPersistentEntity(entityType);

    writeEntity(entity,source,sink,null);
}

此方法说明了为什么嵌套数据被保存为null且不会被跳过。只是将Map放在里面。

因此,下一种方法以这种方式使用反射。因此,如果它是一个空值,那就跳过它:

protected void writeProperties(ElasticsearchPersistentEntity<?> entity,PersistentPropertyAccessor<?> accessor,MapValueAccessor sink) {

    for (ElasticsearchPersistentProperty property : entity) {

        if (!property.isWritable()) {
            continue;
        }

        Object value = accessor.getProperty(property);

        if (value == null) {
            continue;
        }

        if (property.hasPropertyConverter()) {
            ElasticsearchPersistentPropertyConverter propertyConverter = property.getPropertyConverter();
            value = propertyConverter.write(value);
        }

        if (!isSimpleType(value)) {
            writeProperty(property,value,sink);
        } else {
            Object writeSimpleValue = getWriteSimpleValue(value);
            if (writeSimpleValue != null) {
                sink.set(property,writeSimpleValue);
            }
        }
    }
}

没有官方解决方案。所以我创建了一个Jira ticket

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)