Doron
Doron

Reputation: 3256

How do I update multiple items in ElasticSearch?

Let's say I have a tag type in an ElasticSearch index, with the following mapping:

{
    "tag": {
        "properties": {
            "tag": {"type": "string", "store": "yes"},
            "aliases": {"type": "string"}
        }
    }
}

Each entry is a tag, and an array of aliases to that tag. Here is an example item:

{
    "word": "weak",
    "aliases": ["anemic", "anaemic", "faint", "flimsy"]
}

From time to time, I want to add new tag words with their aliases, and add new aliases to existing tag words.

Adding new tag words with their aliases is easy, it's just a new Document. However, how can I add new aliases to existing tag words in a sane way?

I know I can just search for the tag word, get its document, search to see if the alias already exists in the array of aliases, if not add it, than save. However - this does not sound like a good solution.

Is there a way to do a bulk update?

Upvotes: 15

Views: 59964

Answers (9)

Rishabh Rawat
Rishabh Rawat

Reputation: 1194

You can use the ElasticSeach Bulk API for updating the multiple documents using a single API call

CURL example

curl --location --request POST 'localhost:9200/whatsapp/_bulk' \
--header 'Content-Type: application/json' \
--data-raw '{ "update" : {"_id" : 692, "_index" : "whatsapp","_type":"_doc","retry_on_conflict" : 3} }
{ "doc" : {"thread_status" : 1} }
{ "update" : {"_id" : 693, "_index" : "whatsapp","_type":"_doc","retry_on_conflict" : 3} }
{ "doc" : {"thread_status" : 1} }

'

NOTE The final line of data must end with a newline character \n. That' why you will notice ' at the end line of json.

Upvotes: 1

imotov
imotov

Reputation: 30163

All updates in ElasticSearch are done by finding the record, deleting the old version and adding the new version. You can save a little bit on moving records all the way to the client by using Update API. It would still require finding the record though.

What you, probably, want is Update by query.

Upvotes: 11

Rockoder
Rockoder

Reputation: 794

This works for me.

input_list.dat:

{ "index" : { "_index": "my_index", "_type": "my_type", "_id": "existing-value" } }

{ "Field_to_update": "New_Value" }

{ "index" : { "_index": "my_index", "_type": "my_type", "_id": "existing_value" } }

{ "Field_to_update": "New_Value" }

Command:

curl -k -XPOST 'https://my_host:9200/my_url/_bulk' --data-binary "@input_list.dat"; echo

Upvotes: 5

PhaedrusTheGreek
PhaedrusTheGreek

Reputation: 584

Elasticsearch 2.3.0 introduced the Update By Query API as part of the long awaited Reindex API.

As an example, here is how you could update all documents to delete a certain field if it exists:

POST /myindex/mytype/_update_by_query
{
  "script": {
    "inline": "ctx._source.remove(\"remove\")"
  },
  "query": {
    "exists": {
      "field": "remove"
    }
  }
}

The above example uses inline scripting, so be sure to enable it in elasticsearch.yml with script.inline: on.

Upvotes: 4

ashisahu
ashisahu

Reputation: 397

You can do the same using spring java client using the following code. Following are the dependencies used in the code.

import org.elasticsearch.action.update.UpdateRequest;

import org.elasticsearch.index.query.QueryBuilder;

import org.springframework.data.elasticsearch.core.query.UpdateQuery;

import org.springframework.data.elasticsearch.core.query.UpdateQueryBuilder;

private UpdateQuery updateExistingDocument(String Id) {
    // Add updatedDateTime, CreatedDateTime, CreateBy, UpdatedBy field in existing documents in Elastic Search Engine
    UpdateRequest updateRequest = new UpdateRequest().doc("UpdatedDateTime", new Date(), "CreatedDateTime", new Date(), "CreatedBy", "admin", "UpdatedBy", "admin");

    // Create updateQuery
    UpdateQuery updateQuery = new UpdateQueryBuilder().withId(Id).withClass(ElasticSearchDocument.class).build();
    updateQuery.setUpdateRequest(updateRequest);

    // Execute update
     elasticsearchTemplate.update(updateQuery);
}

Upvotes: 0

Eric Vidal
Eric Vidal

Reputation: 29

Elastic Search has a Update API. With that API you can do the following:

curl -XPOST 'localhost:9200/test/tag/weak/_update' -d '{
    "script" : "ctx._source.aliases += faint"
}'

Upvotes: 2

Varshaan
Varshaan

Reputation: 593

Try this using _bulk:

http://127.0.0.1:9200/myindex/type/_bulk
{
"update": {
    "_index": "myindex",
    "_type": "type",
    "_id": "myid"
}
}{
"doc": {
    "field": "new value"
}
}{
"update": {
    "_index": "myindex",
    "_type": "type",
    "_id": "id"
}
}{
"doc": {
    "field": "new value"
}
}

Upvotes: 15

Mohit
Mohit

Reputation: 1755

Elasticsearch's bulk APIs can be used for update requests as well, at least for the Java client.

List list = new Arraylist();
list.add("hello");
BulkProcessor bulk = new BulkProcessor();
UpdateRequest update = new UpdateRequest("index", "type", "id1");
update.script("ctx._source.aliases+= newaliases");  //dynamic script
update.addScriptParam("newaliases", list);
bulk.add(update);

Note that dynamic scripting is disabled in newer versions of elasticsearch. Either enable that or use pre-compiled scripts for using this feature.

Upvotes: 0

Mehmet Uyarovic
Mehmet Uyarovic

Reputation: 314

Also if you add same value with same id, it will automatically update older data.

Upvotes: 0

Related Questions