2016-11-22 830 views
3

我有一个包含许多在elasticsearch上索引的字段(嵌套)的文档。例如:使用Spring Data 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 

} 

在服务类我愿做部分更新与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); 
    } 
} 

保存方法将覆盖整个文档:

{ 
    "id" : 1, 
    "username" : "...", 
    "address" : "..." 
} 

部分udpdate似乎不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)。

任何人都可以给我一个更好的解决方案吗?

回答

4

而是兼具ElasticsearchTemplateUserElasticsearchRepository注入到你的UserServiceClass的,你可以实现自己的定制库,让您现有的UserElasticsearchRepository扩展它。

我假设您现有的UserElasticsearchRepository看起来像这样。

public interface UserElasticsearchRepository extends ElasticsearchRepository<User, String> { 
    .... 
} 

您必须创建新的接口名UserElasticsearchRepositoryCustom。在此界面中,您可以列出您的自定义查询方法。

public interface UserElasticsearchRepositoryCustom { 

    public void updateAddress(User user, String updatedAddress); 

} 

然后通过创建一个名为UserElasticsearchRepositoryImpl类实现您的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); 
    } 
} 

后里面实现自定义的方法,只是扩展了您UserElasticsearchRepositoryUserElasticsearchRepositoryCustom所以它应该看起来像这样。

public interface UserElasticsearchRepository extends ElasticsearchRepository<User, String>, MessageRepositoryCustom { 
    .... 
} 

最后,你的服务代码应该看起来像这样。

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); 
    } 
} 

您也可以将您的用户发现逻辑到自定义库中的逻辑,以及让你可以只通过用户名和地址的方法。希望这是有帮助的。

1

您还可以使用ElasticSearchTemplate来获取您的User对象而不是存储库接口。您可以使用NativeSearchQueryBuilder和其他类来构建您的查询。有了这个,你可以避免你的班级中有两个类似的参考。让我知道这是否能解决您的问题。

+0

谢谢Shahnaz,在我的最终解决方案中,我只使用ElasticSearchTemplate来读取和更新用户对象。但我希望可以用Spring Data Elasticsearch存储库进行部分更新。 – pz74

+0

AFAIK现在没有部分更新可用于存储库,如果您发现某些内容,请让我知道。谢谢 –

相关问题