使用 Spring 数据 Elasticsearch 存储库进行部分更新
Partial update with Spring Data Elasticsearch repository
我有一个文档,其中包含很多字段(有些是嵌套的)在 elasticsearch 上建立了索引。例如:
{
"id" : 1,
"username" : "...",
"name" : "...",
"surname" : "...",
"address" : "...",
"age": 42,
...
"bookmarks" : [{...}, {...}],
"tags" : [{...}, {...}]
}
我的实体中只映射了一些文件(我不想映射整个文档):
@Document(indexName = "...", type = "...")
public class User {
@Id
private int id;
private String username;
private String address;
// getter/setter methods
}
在服务 class 中,我想使用 ElasticsearchRepository 进行部分更新,而不映射实体中的所有文档字段:
public class UserServiceClass {
@Autowired
private UserElasticsearchRepository userElasticsearchRepository;
public void updateAddress(int id, String updatedAddress) {
User user = userElasticsearchRepository.findOne(id);
user.setAddress(updatedAddress);
userElasticsearchRepository.save(user);
}
}
但是save方法覆盖了整个文档:
{
"id" : 1,
"username" : "...",
"address" : "..."
}
ElasticsearchRepository 似乎不支持部分更新。所以我使用了ElasticsearchTemplate,进行了部分更新,例如:
public class UserServiceClass {
@Autowired
private UserElasticsearchRepository userElasticsearchRepository;
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
public void updateAddress(int id, String updatedAddress) {
User user = userElasticsearchRepository.findOne(id);
if (user.getUsername().equals("system")) {
return;
}
IndexRequest indexRequest = new IndexRequest();
indexRequest.source("address", updatedAddress);
UpdateQuery updateQuery = new UpdateQueryBuilder().withId(user.getId()).withClass(User.class).withIndexRequest(indexRequest).build();
elasticsearchTemplate.update(updateQuery);
}
}
但有两个相似的引用(存储库和 ElasticsearchTemplate)似乎有点多余。
谁能建议我更好的解决方案?
您也可以使用 ElasticSearchTemplate 来获取您的用户对象而不是存储库接口。您可以使用 NativeSearchQueryBuilder 和其他 classes 来构建您的查询。有了这个,您可以避免来自 class 的两个相似引用。如果这能解决您的问题,请告诉我。
无需将 ElasticsearchTemplate 和 UserElasticsearchRepository 都注入您的 UserServiceClass,您可以实施您自己的 自定义存储库 并让您现有的 UserElasticsearchRepository 扩展它。
我假设您现有的 UserElasticsearchRepository 看起来像这样。
public interface UserElasticsearchRepository extends ElasticsearchRepository<User, String> {
....
}
您必须创建新的接口名称 UserElasticsearchRepositoryCustom。在此界面中,您可以列出您的自定义查询方法。
public interface UserElasticsearchRepositoryCustom {
public void updateAddress(User user, String updatedAddress);
}
然后通过创建一个名为 UserElasticsearchRepositoryImpl 的 class 来实现您的 UserElasticsearchRepositoryCustom 并在内部实现您的自定义方法并注入 ElasticsearchTemplate
public class UserElasticsearchRepositoryImpl implements UserElasticsearchRepositoryCustom {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Override
public void updateAddress(User user, String updatedAddress){
IndexRequest indexRequest = new IndexRequest();
indexRequest.source("address", updatedAddress);
UpdateQuery updateQuery = new UpdateQueryBuilder().withId(user.getId()).withClass(User.class).withIndexRequest(indexRequest).build();
elasticsearchTemplate.update(updateQuery);
}
}
之后,只需使用 UserElasticsearchRepositoryCustom 扩展您的 UserElasticsearchRepository,它应该看起来像这样。
public interface UserElasticsearchRepository extends ElasticsearchRepository<User, String>, UserElasticsearchRepositoryCustom {
....
}
最后,您的服务代码应该如下所示。
public class UserServiceClass {
@Autowired
private UserElasticsearchRepository userElasticsearchRepository;
public void updateAddress(int id, String updatedAddress) {
User user = userElasticsearchRepository.findOne(id);
if (user.getUsername().equals("system")) {
return;
}
userElasticsearchRepository.updateAddress(user,updatedAddress);
}
}
您也可以将用户查找逻辑移至自定义存储库逻辑中,这样您就可以在方法中仅传递用户 ID 和地址。希望这对您有所帮助。
我有一个文档,其中包含很多字段(有些是嵌套的)在 elasticsearch 上建立了索引。例如:
{
"id" : 1,
"username" : "...",
"name" : "...",
"surname" : "...",
"address" : "...",
"age": 42,
...
"bookmarks" : [{...}, {...}],
"tags" : [{...}, {...}]
}
我的实体中只映射了一些文件(我不想映射整个文档):
@Document(indexName = "...", type = "...")
public class User {
@Id
private int id;
private String username;
private String address;
// getter/setter methods
}
在服务 class 中,我想使用 ElasticsearchRepository 进行部分更新,而不映射实体中的所有文档字段:
public class UserServiceClass {
@Autowired
private UserElasticsearchRepository userElasticsearchRepository;
public void updateAddress(int id, String updatedAddress) {
User user = userElasticsearchRepository.findOne(id);
user.setAddress(updatedAddress);
userElasticsearchRepository.save(user);
}
}
但是save方法覆盖了整个文档:
{
"id" : 1,
"username" : "...",
"address" : "..."
}
ElasticsearchRepository 似乎不支持部分更新。所以我使用了ElasticsearchTemplate,进行了部分更新,例如:
public class UserServiceClass {
@Autowired
private UserElasticsearchRepository userElasticsearchRepository;
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
public void updateAddress(int id, String updatedAddress) {
User user = userElasticsearchRepository.findOne(id);
if (user.getUsername().equals("system")) {
return;
}
IndexRequest indexRequest = new IndexRequest();
indexRequest.source("address", updatedAddress);
UpdateQuery updateQuery = new UpdateQueryBuilder().withId(user.getId()).withClass(User.class).withIndexRequest(indexRequest).build();
elasticsearchTemplate.update(updateQuery);
}
}
但有两个相似的引用(存储库和 ElasticsearchTemplate)似乎有点多余。
谁能建议我更好的解决方案?
您也可以使用 ElasticSearchTemplate 来获取您的用户对象而不是存储库接口。您可以使用 NativeSearchQueryBuilder 和其他 classes 来构建您的查询。有了这个,您可以避免来自 class 的两个相似引用。如果这能解决您的问题,请告诉我。
无需将 ElasticsearchTemplate 和 UserElasticsearchRepository 都注入您的 UserServiceClass,您可以实施您自己的 自定义存储库 并让您现有的 UserElasticsearchRepository 扩展它。
我假设您现有的 UserElasticsearchRepository 看起来像这样。
public interface UserElasticsearchRepository extends ElasticsearchRepository<User, String> {
....
}
您必须创建新的接口名称 UserElasticsearchRepositoryCustom。在此界面中,您可以列出您的自定义查询方法。
public interface UserElasticsearchRepositoryCustom {
public void updateAddress(User user, String updatedAddress);
}
然后通过创建一个名为 UserElasticsearchRepositoryImpl 的 class 来实现您的 UserElasticsearchRepositoryCustom 并在内部实现您的自定义方法并注入 ElasticsearchTemplate
public class UserElasticsearchRepositoryImpl implements UserElasticsearchRepositoryCustom {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Override
public void updateAddress(User user, String updatedAddress){
IndexRequest indexRequest = new IndexRequest();
indexRequest.source("address", updatedAddress);
UpdateQuery updateQuery = new UpdateQueryBuilder().withId(user.getId()).withClass(User.class).withIndexRequest(indexRequest).build();
elasticsearchTemplate.update(updateQuery);
}
}
之后,只需使用 UserElasticsearchRepositoryCustom 扩展您的 UserElasticsearchRepository,它应该看起来像这样。
public interface UserElasticsearchRepository extends ElasticsearchRepository<User, String>, UserElasticsearchRepositoryCustom {
....
}
最后,您的服务代码应该如下所示。
public class UserServiceClass {
@Autowired
private UserElasticsearchRepository userElasticsearchRepository;
public void updateAddress(int id, String updatedAddress) {
User user = userElasticsearchRepository.findOne(id);
if (user.getUsername().equals("system")) {
return;
}
userElasticsearchRepository.updateAddress(user,updatedAddress);
}
}
您也可以将用户查找逻辑移至自定义存储库逻辑中,这样您就可以在方法中仅传递用户 ID 和地址。希望这对您有所帮助。