2022-01-30 - world ugliest increment

some time ago i was working on a small project, that used elasticsearch as a data backend. i was facing an interesting issue, of having to do atomic increment, on a record. say under foo.bar.data.answer key. the problem however was that the target record could already exist… or not. if it did exist, it could already have some value assigned… or could have been created by a different request, that do not set that field at all.

the answer was painful, to say the least. i've ended up with this:

  "script": {
    "source": "if ( ctx._source.containsKey('foo') ) { ctx._source.foo.bar.data.answer += 1; } else { ctx._source.put('foo', params); }",
    "params": {
      "bar": {
        "data": {
          "answer": 1
  "upsert": {
    "date": "2020-07-20",
    "xxx": "ain't gonna do anything the first time - either upsert OR script will work..."

so… ES will always execute either upsert or script. if there entry is not there, upsert will create some generic entry template. if the elemet exists, script will be called instead. script.source has a simple program – if given key (“branch”) exists, action is executed (here – incrementing a value). if not, content of params is put under the key foo, thus effectively crating some initial value, that later increments can work with.

in my case, the problem was even more extreme, as the path itself depended on some runtime values, thus this “incremenation” code was in fact a metaprogram, generating ES script, based on the path and values needed.

well, at the end of the day –it worked. but i guess this deserves a prize for a worst incrementation ever. it would be really nice to have ES feature, that would allow to address an existing key or create new, with a default value, in case it does not exist. such an operation would save a lot of effort.

blog/2022/01/30/2022-01-30_-_world_ugliest_increment.txt · Last modified: 2022/01/30 20:11 by basz
Back to top
Valid CSS Driven by DokuWiki Recent changes RSS feed Valid XHTML 1.0