Reputation: 85
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
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
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
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
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
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