Lone Learner
Lone Learner

Reputation: 20628

Why does Elasticsearch _update with "script" using "params" not deleting document?

I performed these experiments with Elasticsearch 6.1.3.

Experiment 1: script as a single line

Here is my shell script:

# Index document.
curl -sX PUT -H 'Content-Type: application/json' \
      http://localhost:9200/a/a/1?pretty -d '{ "n": 10 }'

# Delete document (single-line script)
curl -siX POST -H 'Content-Type: application/json' \
     http://localhost:9200/a/a/1/_update?pretty -d '{

    "script": "ctx.op = ctx._source.n == 10 ? \"delete\" : \"none\""
}'

# Print document.
sleep 1
curl -si http://localhost:9200/a/a/1?pretty

Here is the output from the last two curl commands:

+ curl -siX POST -H 'Content-Type: application/json' 'http://localhost:9200/a/a/1/_update?pretty' -d '{

    "script": "ctx.op = ctx._source.n == 10 ? \"delete\" : \"none\""
}'
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 213

{
  "_index" : "a",
  "_type" : "a",
  "_id" : "1",
  "_version" : 4,
  "result" : "deleted",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 20,
  "_primary_term" : 1
}
+ sleep 1
+ curl -si 'http://localhost:9200/a/a/1?pretty'
HTTP/1.1 404 Not Found
content-type: application/json; charset=UTF-8
content-length: 72

{
  "_index" : "a",
  "_type" : "a",
  "_id" : "1",
  "found" : false
}

As expected, the document has been deleted.

Experiment 2: script as an object

Here is my shell script:

# Index document.
curl -sX PUT -H 'Content-Type: application/json' \
      http://localhost:9200/a/a/1?pretty -d '{ "n": 10 }'

# Print document.
sleep 1
curl http://localhost:9200/a/a/1?pretty

# Delete document (single-line script)
curl -siX POST -H 'Content-Type: application/json' \
     http://localhost:9200/a/a/1/_update?pretty -d '{

    "script": {
        "inline": "ctx.op = ctx._source.n == params.count ? \"delete\" : \"none\"",
        "params": {
            "count": 10
        }
    }
}'

# Print document.
sleep 1
curl -si http://localhost:9200/a/a/1?pretty

Here is the output from the last two curl commands:

+ curl -siX POST -H 'Content-Type: application/json' 'http://localhost:9200/a/a/1/_update?pretty' -d '{

    "script": {
        "inline": "ctx.op = ctx._source.n == params.count ? \"delete\" : \"none\"",
        "params": {
            "count": 10
        }
    }
}'
HTTP/1.1 200 OK
Warning: 299 Elasticsearch-6.1.3-af51318 "Deprecated field [inline] used, expected [source] instead" "Sat, 10 Feb 2018 10:58:57 GMT"
content-type: application/json; charset=UTF-8
content-length: 213

{
  "_index" : "a",
  "_type" : "a",
  "_id" : "1",
  "_version" : 2,
  "result" : "deleted",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 22,
  "_primary_term" : 1
}
+ sleep 1
+ curl -si 'http://localhost:9200/a/a/1?pretty'
HTTP/1.1 404 Not Found
content-type: application/json; charset=UTF-8
content-length: 72

{
  "_index" : "a",
  "_type" : "a",
  "_id" : "1",
  "found" : false
}

As expected, the document has been deleted.

Experiment 3: script as a single line using params

Here is my shell script:

# Index document.
curl -sX PUT -H 'Content-Type: application/json' \
      http://localhost:9200/a/a/1?pretty -d '{ "n": 10 }'

# Print document.
sleep 1
curl http://localhost:9200/a/a/1?pretty

# Delete document (single-line script)
curl -siX POST -H 'Content-Type: application/json' \
     http://localhost:9200/a/a/1/_update?pretty -d '{

    "script": "ctx.op = ctx._source.n == params.count ? \"delete\" : \"none\"",
    "params": {
        "count": 10
    }
}'

# Print document.
sleep 1
curl -si http://localhost:9200/a/a/1?pretty

Here is the output from the last two curl commands:

+ curl -siX POST -H 'Content-Type: application/json' 'http://localhost:9200/a/a/1/_update?pretty' -d '{

    "script": "ctx.op = ctx._source.n == params.count ? \"delete\" : \"none\"",
    "params": {
        "count": 10
    }
}'
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 169

{
  "_index" : "a",
  "_type" : "a",
  "_id" : "1",
  "_version" : 1,
  "result" : "noop",
  "_shards" : {
    "total" : 0,
    "successful" : 0,
    "failed" : 0
  }
}
+ sleep 1
+ curl -si 'http://localhost:9200/a/a/1?pretty'
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 123

{
  "_index" : "a",
  "_type" : "a",
  "_id" : "1",
  "_version" : 1,
  "found" : true,
  "_source" : {
    "n" : 10
  }
}

Why was the document not deleted this time?

As per the documentation at https://www.elastic.co/guide/en/elasticsearch/guide/current/partial-updates.html this should have deleted the document. Quoting the documentation:

We can even choose to delete a document based on its contents, by setting ctx.op to delete:

POST /website/blog/1/_update
{
   "script" : "ctx.op = ctx._source.views == count ? 'delete' : 'none'",
    "params" : {
        "count": 1
    }
}

Why did this not work?

Upvotes: 3

Views: 590

Answers (1)

Andrei Stefan
Andrei Stefan

Reputation: 52368

I think that's a mistake in the Definitive Guide, which actually is kind of work in progress (the current valid version kind of applies to 2.x version of ES). The mistake is the use of params outside a script enclosure basically. Your experiment #2 should be the correct format of using params with scripts for a partial _update.

But, what I believe it's also wrong is that ES doesn't return an error message when this syntax is used. Thus, I created https://github.com/elastic/elasticsearch/issues/28740 for this.

Upvotes: 1

Related Questions