lucene并不支持部分Field的更新,updateDocument的实现逻辑实际是delete-add。lucene-plus基于updateDocument的实现实现了部分feild的更新,大致逻辑:query-delete-add。
DocumentPlusService#updateDocument:
/**
* 更新文档
* @param indexName 索引名称
* @param builder 更新文档的条件
* @param params 参数
*/
public void updateDocument(String indexName, BooleanQuery.Builder builder, Map<String, Object> params) throws IOException {
List<Document> docList = CollUtil.newArrayList();
SearchAfterRequestDTO searchAfterRequestDTO = new SearchAfterRequestDTO();
searchAfterRequestDTO.setIndexName(indexName);
searchAfterRequestDTO.setBuilder(builder);
searchAfterRequestDTO.setPageSize(1000);
SortField sortField = new SortField(IndexEnum.TIMESTAMP.getName(), Type.LONG);
searchAfterRequestDTO.setSort(new Sort(sortField));
boolean flag = true;
SearchAfterResultDTO resultDTO;
while (flag) {
resultDTO = this.searchByAfter(searchAfterRequestDTO);
if(CollUtil.isEmpty(resultDTO.getResult())) {
flag = false;
continue;
}
docList.addAll(resultDTO.getResult());
searchAfterRequestDTO.setLastScoreDoc(resultDTO.getLastDoc());
}
// 删除
this.deleteDocument(indexName, builder);
// 新增
Map<String, Object> mergeParams;
for (Document doc : docList) {
mergeParams = this.mergeFields(doc.getFields(), params);
this.addDocument(indexName, mergeParams);
}
}
1.根据指定条件检索出所有相关的文档,这里用到了lucene-plus已封装的的SearchByAfter;
2.根据指定条件执行删除文档;
3.实现数据合并,重新保存文档,合并文档逻辑:
/**
* 合并文档
* @param sourceFields 文档
* @param targetMap 新字段值
*/
private Map<String, Object> mergeFields(List<IndexableField> sourceFields, Map<String, Object> targetMap) {
Set<String> systemFields = CollUtil.newHashSet(IndexEnum.TIMESTAMP.getName());
Map<String, Object> params = CollUtil.newHashMap();
sourceFields.stream()
.filter(t->!systemFields.contains(t.name()))
.filter(t->!targetMap.containsKey(t.name())).forEach(t->params.put(t.name(), t.stringValue()));
targetMap.forEach((key, value) -> {
if(!systemFields.contains(key)) {
params.put(key, value);
}
});
return params;
}