Spring Data Elasticsearch:检测映射差异
Spring Data Elasticsearch : detect mapping differences
在 Spring Data Elasticsearch 中,有没有一种方法可以检测索引上的映射与从实体对象创建的映射不匹配?
即
我允许 Spring Data Elasticsearch 最初从用 @Document
和 @Field
注释的实体模型创建映射
稍后我向模型添加了一个新字段,但没有更新索引映射,这个新字段将无法正确配置,直到我重新索引到新映射
那么有没有一种方法可以检测到这种差异,这样我就可以知道哪些索引需要重新创建它们的映射,以及哪些文档需要重新编制索引?
这是一个有趣的问题,但答案并不复杂。
假设我们有一个要存储在 foo
索引中的 Foo
实体 class 和使用此 class 的 FooRepository
。在
应用程序启动,当索引不存在时,将使用从实体派生的映射创建它。
为了检测从 class 派生的映射和存储在 Elasticsearch 中的映射的变化,您可以使用
像这样的方法:
@Component
public class FooMappingValidator {
private static final Logger LOGGER = LoggerFactory.getLogger(FooMappingValidator.class);
private final ObjectMapper objectMapper = new ObjectMapper();
private final ElasticsearchOperations operations;
public FooMappingValidator(ElasticsearchOperations operations) {
this.operations = operations;
}
@Autowired
public void checkFooMapping() {
var indexOperations = operations.indexOps(Foo.class);
if (indexOperations.exists()) {
LOGGER.info("checking if mapping for Foo changed");
var mappingFromEntity = indexOperations.createMapping();
var mappingFromEntityNode = objectMapper.valueToTree(mappingFromEntity);
var mappingFromIndexNode = objectMapper.valueToTree(indexOperations.getMapping());
if (!mappingFromEntityNode.equals(mappingFromIndexNode)) {
LOGGER.info("mapping for class Foo changed!");
indexOperations.putMapping(mappingFromEntity);
}
}
}
}
这是一个 Spring 组件,它注入了 ElasticsearchOperations
并且有一个注释为
@Autowired
。在 bean 中注入所有依赖项后,将执行自动装配方法。这表示
它在正常应用程序逻辑启动之前运行。
在这个方法中,我们首先为我们的实体 class 获取一个 IndexOperations
实例。接下来我们检查索引是否存在,
如果没有,我们就不需要检查。
在下一步中,我们从实体中获取当前映射并将其转换为 JsonNode
并对
我们从 Elasticsearch 检索的映射。我们在这里使用 JsonNode
s 因为有一个 equals()
方法
做我们需要的比较。
如果我们检测到两个映射不同,我们将使用 putMapping()
方法将新映射写入索引。
注意:
这仅在将新属性添加到实体时有效,因为在 Elasticsearch 中无法更改现有映射,
那里你需要重建索引。
在 Spring Data Elasticsearch 中,有没有一种方法可以检测索引上的映射与从实体对象创建的映射不匹配?
即
我允许 Spring Data Elasticsearch 最初从用 @Document
和 @Field
稍后我向模型添加了一个新字段,但没有更新索引映射,这个新字段将无法正确配置,直到我重新索引到新映射
那么有没有一种方法可以检测到这种差异,这样我就可以知道哪些索引需要重新创建它们的映射,以及哪些文档需要重新编制索引?
这是一个有趣的问题,但答案并不复杂。
假设我们有一个要存储在 foo
索引中的 Foo
实体 class 和使用此 class 的 FooRepository
。在
应用程序启动,当索引不存在时,将使用从实体派生的映射创建它。
为了检测从 class 派生的映射和存储在 Elasticsearch 中的映射的变化,您可以使用 像这样的方法:
@Component
public class FooMappingValidator {
private static final Logger LOGGER = LoggerFactory.getLogger(FooMappingValidator.class);
private final ObjectMapper objectMapper = new ObjectMapper();
private final ElasticsearchOperations operations;
public FooMappingValidator(ElasticsearchOperations operations) {
this.operations = operations;
}
@Autowired
public void checkFooMapping() {
var indexOperations = operations.indexOps(Foo.class);
if (indexOperations.exists()) {
LOGGER.info("checking if mapping for Foo changed");
var mappingFromEntity = indexOperations.createMapping();
var mappingFromEntityNode = objectMapper.valueToTree(mappingFromEntity);
var mappingFromIndexNode = objectMapper.valueToTree(indexOperations.getMapping());
if (!mappingFromEntityNode.equals(mappingFromIndexNode)) {
LOGGER.info("mapping for class Foo changed!");
indexOperations.putMapping(mappingFromEntity);
}
}
}
}
这是一个 Spring 组件,它注入了 ElasticsearchOperations
并且有一个注释为
@Autowired
。在 bean 中注入所有依赖项后,将执行自动装配方法。这表示
它在正常应用程序逻辑启动之前运行。
在这个方法中,我们首先为我们的实体 class 获取一个 IndexOperations
实例。接下来我们检查索引是否存在,
如果没有,我们就不需要检查。
在下一步中,我们从实体中获取当前映射并将其转换为 JsonNode
并对
我们从 Elasticsearch 检索的映射。我们在这里使用 JsonNode
s 因为有一个 equals()
方法
做我们需要的比较。
如果我们检测到两个映射不同,我们将使用 putMapping()
方法将新映射写入索引。
注意:
这仅在将新属性添加到实体时有效,因为在 Elasticsearch 中无法更改现有映射, 那里你需要重建索引。