Mark Juszczec
Mark Juszczec

Reputation: 85

spring-data-elasticsearch and update

i'm using spring-data-elasticsearch to do CRUD operations.

I have a custom Repository that extends ElasticsearchRepository.

Ultimately ElasticsearchRepository extends CrudRepository which implies updating an existing record is possible.

The question is, how do you accomplish this? I haven't found a method called "update()"

I thought doing the following would work (code stolen from https://github.com/BioMedCentralLtd/spring-data-elasticsearch-sample-application)

    //create
    Book book = new Book();
    book.setId("123455");
    book.setName("Spring Data Elasticsearch");
    book.setVersion(System.currentTimeMillis());
    repository.save(book);

    //update
    book.setName("THIS IS A COMPLETELY NEW TITLE");
    repository.save(book); 

However the 2nd save throws an InvocationTargetException

Examining it with the debugger shows:

[book][0] [book][123455]: version conflict, current [1447792071681], provided [1447792071681]

The Book object looks like:

@Document(indexName = "book",type = "book" , shards = 1, replicas = 0, indexStoreType = "memory", refreshInterval = "-1")
public class Book {

    @Id
    private String id;
    private String name;
    private Long price;
    @Version
    private Long version;

    public Map<Integer, Collection<String>> getBuckets() {
        return buckets;
    }

    public void setBuckets(Map<Integer, Collection<String>> buckets) {
        this.buckets = buckets;
    }

    @Field(type = FieldType.Nested)
    private Map<Integer, Collection<String>> buckets = new HashMap();

    public Book(){}

    public Book(String id, String name,Long version) {
        this.id = id;
        this.name = name;
        this.version = version;
    }

    getters and setters removed for space

}

My Repository code is even simpler:

import org.springframework.data.elasticsearch.entities.Book;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

public interface BookRepository extends ElasticsearchRepository<Book, Long> {

}

Do I have to provide an update method?

EDIT:

Nevermind. I changed the update to:

    //update
    book.setName("THIS IS A COMPLETELY NEW TITLE");
    book.setVersion(System.currentTimeMillis());
    repository.save(book); 

and it updated the record.

Upvotes: 4

Views: 13178

Answers (5)

Prashant Srivastava
Prashant Srivastava

Reputation: 1

 XContentType contentType = 
org.elasticsearch.client.Requests.INDEX_CONTENT_TYPE;
public XContentBuilder getBuilder(User assign){
 try {
    XContentBuilder builder = XContentFactory.contentBuilder(contentType);
     builder.startObject();
     Map<String,?> assignMap=objectMap.convertValue(assign, Map.class);
              builder.field("assignee",assignMap);
     return builder;
    } catch (IOException e) {
            log.error("custom field index",e);
 }
  IndexRequest indexRequest = new IndexRequest();
    indexRequest.source(getBuilder(assign));
    UpdateQuery updateQuery = new UpdateQueryBuilder()
                                    .withType(<IndexType>)
                                    .withIndexName(<IndexName>)
                                    .withId(String.valueOf(id))
                                    .withClass(<IndexClass>)
                                    .withIndexRequest(indexRequest)
                                    .build();

Upvotes: 0

Jason DeMorrow
Jason DeMorrow

Reputation: 699

The second update fails because you're trying to update an entity whose version hasn't changed. The error message you're getting is ES telling you, "hey, you can't save the same version twice!" Try this:

//create
Book book = new Book();
book.setId("123455");
book.setName("Spring Data Elasticsearch");
book.setVersion(System.currentTimeMillis());
repository.save(book);

//update
book.setName("THIS IS A COMPLETELY NEW TITLE");
book.setVersion(System.currentTimeMillis()); // you're saving a new version
repository.save(book); 

Upvotes: 2

hill
hill

Reputation: 71

I updated indexed document as follows code snippet:

        IndexRequest indexRequest = new IndexRequest(INDEX_NAME,INDEX_NAME,docid);
        indexRequest.source(fldName, fldValue);
        UpdateRequest updateRequest = new UpdateRequest();
        updateRequest.index(INDEX_NAME);
        updateRequest.type(INDEX_NAME);
        updateRequest.id(docid);
        updateRequest.doc(indexRequest);
        try {
            UpdateResponse res=client.update(updateRequest).get();
            logger.info("update es {}:{}",fe,res.getGetResult());
        } catch (Exception e) {
            logger.error("update",e);
            throw e;
        }

Upvotes: 1

Shahnaz Khan
Shahnaz Khan

Reputation: 1155

You can use UpdateQuery and ElasticSearchTemplate to update any partial document. e.g

    final UpdateRequest updateRequest = new UpdateRequest();
    updateRequest.index(mainIndexName);
    updateRequest.type(typeName);
    updateRequest.id(id);
    updateRequest.doc(XContentFactory.jsonBuilder().startObject()
                        .field("accountType", accountType)
                        .endObject());
    final UpdateQuery updateQuery = new UpdateQueryBuilder().withId(id)
                        .withClass(<DocumentClass>).withUpdateRequest(updateRequest).build();
    UpdateResponse updateResponse =  elasticSearchTemplate.update(updateQuery);

Upvotes: 2

ae6623
ae6623

Reputation: 1

I think the ElasticSearch is a similar to the JSON storage:

if(exist) {
    update it;// push json to cover it
} else {
    add it;// new save();
}

It will update the JSON when Id/Entity is exist, or it will add it.

Upvotes: 0

Related Questions