Preventing document update based on field values

Is there anyway to prevent updating document based on some field?

Eg-

Below documents already present in elastic:
{
"business_address" : "660 Sacramento St",
"business_city" : "San Francisco",
"business_id" : 22
}

And if someone is trying to update above document then it should prevent it bcz "business_id" : 22

Is there anyway to prevent it?

Hey @ashish25 !

You might use script updating for that, something similar to:

PUT /index_name/_update/doc_id
{
  "script": {
    "lang": "painless", // Scripting language (other options available)
    "source": "if (ctx._source.field_name.value != 'undesired_value') { ... update logic ... }"
  }
}

Or, you could implement the logic in your application, and retrieve the doc first before updating to check the value.

Hope that helps!

Thanks @Carlos_D for your response, just one more question regarding your script above -
if (doc.field_name.value != 'undesired_value') --> will it check the value of document which we are trying to ingest or will it check the value of existing document in elastic?

Hi @ashish25 ! It refers to the current document value. There were some errors in the original script I provided - I updated the script in my previous response to properly use ctx._source to refer to the existing document.

In case you want to check the provided value, I would suggest using script parameters for that. Please check these examples.

Thanks @Carlos_D, I am able to prevent the document via your suggestion.

Is it possible to put this script at index pattern level ? So that the script will be executed for all the documents at the time of ingestion.

Is it possible to put this script at index pattern level ? So that the script will be executed for all the documents at the time of ingestion.

You could use an ingest pipeline to check that, using the fail processor.

Using the ingest pipeline as the final pipeline for the index will perform that check for all ingested documents.

Thank you very much for your response.

I created processor like below:

Processor:

PUT _ingest/pipeline/my-pipeline_test
{
"description": "My optional pipeline description",
"processors": [
{
"drop": {
"description": "Drop documents",
"if": "ctx._source?.status == 'Delivered'"
}
}
]
}

And then trying to POST below document:

POST my-test-stream/_doc/123?pipeline=my-pipeline_test
{
"my-keyword-field": "foo",
"status": "Delivered"
}

And after that when I am trying to update above document like:

POST my-test-stream/_update/123?pipeline=my-pipeline_test
{
"my-keyword-field": "foo1",
"status": "Initiate"
}

It is giving me below error instead of dropping the document:
{
"error" : {
"root_cause" : [
{
"type" : "x_content_parse_exception",
"reason" : "[2:3] [UpdateRequest] unknown field [my-keyword-field]"
}
],
"type" : "x_content_parse_exception",
"reason" : "[2:3] [UpdateRequest] unknown field [my-keyword-field]"
},
"status" : 400
}

And also when I am trying to execute below commands, it got updated successfully instead of dropping the document -
POST my-test-stream/_doc/123?pipeline=my-pipeline_test
{
"my-keyword-field": "foo1",
"status": "Initiate"
}

Please let me know whether I am missing something.

@Carlos_D It seems we can't query the existing document inside processor.
So, is there any other workaround?

I'm able to check the ingested document, but not the existing one on the if section :frowning_face: .

Another think I'd like to check is whether it's possible to do that in a script processor, as the context they receive is different that the if section. But I haven't been able to confirm that yet.

Besides that, I can't think of anything else that is Elasticsearch based - it would have to be dealt with at the client level.

script processor is also not able to query existing document :frowning:
We are having this check at client level but observing some edge scenario where our client is not able to handle it, so trying to explore this option.

Thanks @Carlos_D for all your response.