Johnsa Philip
Johnsa Philip

Reputation: 1835

Update only specific field value in elasticsearch

Is it possible to update some specific fields value in elasticsearch with out overwriting other fields. ?

Upvotes: 119

Views: 224488

Answers (9)

Manas Aggrawal
Manas Aggrawal

Reputation: 36

For me, this worked:

    POST /jira_project/_doc/4c459bbb-8cc2-44c0-a455-f01cfc658017/_update
    {
      "doc":{
        "body": {
          "isDeleted": true,
          "deletedAt": "2023-10-03T11:16:21.489Z"
        }
      }

    }

Explanation:

  1. Here "jira_project" is the index name.
  2. "_doc" is the type of entity you are targeting within that index (this is deprecated in newer versions since by default entities within an index are taken as doc type).
  3. I have updated some keys inside the "body" key, so that's why I mentioned "body" while updating.

Everything else is self-explanatory.

Upvotes: 0

Bal Krishna Jha
Bal Krishna Jha

Reputation: 7206

Make POST call to {{host}}/{{index}}/_doc/{{id}}/_update

with body as

{
    "doc": {
        "field": "value"
    }
}

Output would be similar to

{
    "_index": "{{index}}",
    "_type": "_doc",
    "_id": "{{id}}",
    "_version": 3,
    "result": "updated",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 27,
    "_primary_term": 2
}

Upvotes: 5

Pramod H G
Pramod H G

Reputation: 1613

Update By Query API

Updates documents that match the specified query. If no query is specified, performs an update on every document in the data stream or index without modifying the source, which is useful for picking up mapping changes.

POST http://localhost:9200/INDEX_NAME/_update_by_query
{
  "script": {
    "source": "ctx._source.userName=new_user_name",
    "lang": "painless"
  },
  "query": { 
    "term": {
      "userName": "old_user_name"
    }
  }
}   

In the above example, the userName field value will be updated to new_user_name

Upvotes: 10

Sumit Sood
Sumit Sood

Reputation: 205

Also you can use bulk Update to partially update multiple doc

POST /foo_v1/_bulk?pretty=true&error_trace=true
{"update":{"_index":"foo_v1","_type":"footype","_id":"397"}}
{"doc":{"Name":"foo","EmailId":"[email protected]"}}
{"update":{"_index":"foo_v1","_type":"footype","_id":"398"}}
{"doc":{"Name":"foo1","EmailId":"[email protected]"}}

If you are not sure whether it will be a update or insert like Upsert so you can do :

POST /foo_v1/_bulk?pretty=true&error_trace=true
{"update":{"_index":"foo_v1","_type":"footype","_id":"397"}}
{"doc":{"Name":"foo","EmailId":"[email protected]"}, "doc_as_upsert" : true}

use "doc_as_upsert" : true

Upvotes: 5

Ankit Kumar Rajpoot
Ankit Kumar Rajpoot

Reputation: 5590

Try this

curl -XPOST --header 'Content-Type: application/json' https://search-testarticle-2cwv6oh7wtz3hxowgxv3rprnsa.ap-south-1.es.amazonaws.com/test/_update/4gI4knQB7d5sAgV24YPy -d '{
"doc":  { "name" : "Ankit Singh Raj" }
}'

Upvotes: 2

Marc
Marc

Reputation: 14269

In ES 7.3 the new format is:

POST /myindex/_update/mydocid
{
    "doc" : {
        "myfield": "new value of my field"
    }
}

Upvotes: 97

javanna
javanna

Reputation: 60195

Yes, Elasticsearch supports partial updates. That means that you can submit:

  • a partial document, which will be merged with the existing one
  • a script that will be executed on top of the existing document

Have a look at the update api. In both cases, what happens under the hood, due to how the underlying lucene library works, is that the document to be updated is retrieved, the changes are applied to it, and the old document gets overwritten with the new. At the end of the day it is in fact a complete rewrite of the document, but you don't have to submit the whole document, unless you disabled the _source field, enabled by default, which is the field that allows you to retrieve to whole document in order to apply changes to it.

Upvotes: 29

Sumit Sood
Sumit Sood

Reputation: 205

If you would like to update the existing field value only then you must try this solution:

POST IndexName/_update_by_query
{
  "script": {
    "source": """

   if (ctx._source?.Field != null) 
    {  
        ctx._source.remove('Field');
        ctx._source.put('Field', 'Value');
    }   
    """,
    "lang": "painless"
  },
  "query": {
    "terms": {
        "_id": [
          1 (Replace with Document ID)
        ]
      }
  }
}

If you would like to add new field with value then you must try this solution:

POST IndexName/_update_by_query
{
  "script": {
    "source": """

   if (ctx._source?.NewField == null) 
    {  
        ctx._source.hf.put('NewField', 'Value');
    }   
    """,
    "lang": "painless"
  },
  "query": {
    "terms": {
        "_id": [
          1 (Replace with Document ID)
        ]
      }
  }
}

Upvotes: 12

pedrouan
pedrouan

Reputation: 12910

As a codebased contribution to this answer, the following query may be used:

POST /index/type/100100471/_update
{
    "doc" : {
        "yourProperty" : 10000
    }
}

This query updates yourProperty property only.

As a result, this response appears:

{
   "_index": "index",
   "_type": "type",
   "_id": "100100471",
   "_version": 1,
   "_shards": {
      "total": 0,
      "successful": 1,
      "failed": 0
   }
}

Upvotes: 94

Related Questions