elasticsearchelasticsearch-painlesselasticsearch-scripting

Elasticsearch: count query in _search script


I'm trying to make a single query for updating the one field value in ES index.

I have a index pages which contain information about the pages (id, name, time, parent_page_id, child_count etc)

I can update the field parent_page_id with number of documents which have this page id as parent_page_id

I can update the field with default single value like:

PUT HOST_ADDRESS/pages/_update_by_query
{
  "script": {
    "source": "def child_count = 0; ctx._source.child_count = child_count;",
    "lang": "painless"
  },
  "query": {
    "match_all": {}
  }
}

I'm trying with this code to get child count but its not working.

"source": "def child_count = 0; client.prepareSearch('pages').setQuery(QueryBuilders.termQuery("parent_page_id", "ctx._source.id")).get().getTotal().getDocs().getCount(); ctx._source.child_count = child_count;",
    "lang": "painless"

My question is, how can i make a sub count-query in script to have a real child count in variable child_count


Solution

  • Scripting doesn't work like this — you cannot use java DSL in there. There's no concept of client or QueryBuilders etc in the Painless contexts.

    As such, you'll need to obtain the counts before you proceed to update the doc(s) with a script.

    Tip: scripts are reusable when you store them:

    POST HOST_ADDRESS/_scripts/update_child_count
    {
      "script": {
        "lang": "painless",
        "source": "ctx._source.child_count = params.child_count"
      }
    }
    

    and then apply via the id:

    PUT HOST_ADDRESS/pages/_update_by_query
    {
      "script": {
        "id": "update_child_count",     <-- no need to write the Painless code again
        "params": {
          "child_count": 987
        }   
      },
      "query": {
        "term": {
          "parent_page_id": 123
        }
      }
    }