Dan Ross Dan Ross - 4 months ago 103
Node.js Question

How to create or replace a document in Elasticsearch?

I'm just trying to create or replace a document, but the API docs aren't clear on how to do this.

The upsert example shows a document being created with a

counter
value of
1
:

client.update({
index: 'myindex',
type: 'mytype',
id: '777',
body: {
script: 'ctx._source.counter += 1',
upsert: {
counter: 1
}
}
}, function(error, response) {
// ...
})


I don't need the increment script, so I try to just send an upsert by itself, but I get a 400
Validation Failed: 1: script or doc is missing
:

client.update({
index: "testindex",
type: "testType",
id: 1234,
body: {
upsert: {
itworks: true,
ok: "oh yeah"
}
}
})


Well, let's try something silly and include the doc twice; once under
doc
, which would presumably replace an existing document if there was one, and once under
upsert
, which would be used to create a new document otherwise:

client.update({
index: "testindex",
type: "testType",
id: 1234,
body: {
upsert: {
itworks: true,
ok: "oh yeah"
},
doc: {
itworks: true,
ok: "oh yeah"
}
}
})


That actually worked, 201 Created. 200 OK when I repeat it to replace the doc with a different one:

client.update({
index: "testindex",
type: "testType",
id: 1234,
body: {
upsert: {
whatever: "man"
},
doc: {
whatever: "man"
}
}
})


But when I check the doc (
client.get({index: "testindex", type: "testType", id: 1234})
), I see that instead of replacing the existing doc, the new doc was merged with it.

How do you just replace a doc in Elasticsearch, with the standard Node client? The HTTP API makes it look so simple, but I've tried a bunch of permutations of that in the Node client without success. Is there no replace command? Do I have to delete and then create?

Answer

In Elasticsearch, to replace a document you simply have to index a document with the same ID and it will be replaced automatically.

If you would like to update a document you can either do a scripted update, a partial update or both.

To do a partial doc update you simply

Partial document update:

client.update({
  index: 'myindex',
  type: 'mytype',
  id: '1',
  body: {
    // put the partial document under the `doc` key
    doc: {
      title: 'Updated'
    }
  }
}, function (error, response) {
  // ...
})

Scripted update:

client.update({ index: 'myindex', type: 'mytype', id: '1', body: { script: 'ctx._source.tags += tag', params: { tag: 'some new tag' } } }, function (error, response) { // ... });

More info in Elasticsearch JS documentation