问题描述
我有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 (将#修改为@)