javatemplateselasticsearchmustacheelasticsearch-template

Elasticsearch Mustache optional parameters


I've been struggling with Elasticsearch templates, specifically in optional parameters. I'd like to add optional filters there. This is the code snippet I was trying out:

{
  "filter" : {
    "bool" : {
      "must" : [
        {{#ProductIDs.0}}
        { "terms" : { "Product.ProductID" : [{{#ProductIDs}}{{.}},{{/ProductIDs}}] } }
        {{/ProductIDs.0}}
      ]
    }
  }
}

Of course I replaced " with \", uglified it, wrapped it up in { "template" :"_snippet_above_" }.

Now when I'm trying to call it using the following:

GET /statistic/_search/template
{
    "template": {
        "id": "test" 
    },
    "params": {
        "ProductIDs": [1,2]
    }
}

It ignores parameter that I've provided, however when I try to do that in official mustache.io demo page - it works just fine.

I tried {{#ProductIDs.length}} option too - it didn't work out. After doing some research I've found out that there is one difference between mustache.js and mustache.java. I assumed that Elasticsearch uses JAVA version and it doesn't support length parameter, so I have to rely on isEmpty. So I've rewritten my query as follows:

{
  "filter" : {
    "bool" : {
      "must" : [
        {{^ProductIDs.isEmpty}}
        { "terms" : { "Product.ProductID" : [{{#ProductIDs}}{{.}},{{/ProductIDs}}] } }
        {{/ProductIDs.isEmpty}}
      ]
    }
  }
}

Now when I query template with ProductIDs list - it works fine, however if I remove parameter, it brings no results. I assume it generates this:

{
  "filter" : {
    "bool" : {
      "must" : [
        { "terms" : { "Product.ProductID" : [] } }
      ]
    }
  }
}

If I send empty array as Parameter - it works fine.

GET /statistic/_search/template
{
    "template": {
        "id": "test" 
    },
    "params": {
        "ProductIDs": []
    }
}

I assume this happens because "ProductIDs" are undefined and not empty.

Is there a way to cath this condition in mustache.java so I can ignore these parameters?

tl;dr; The issue is that if I don't specify parameter in my search request via template, my condition is rendered as an empty array, see this:

{
  "filter" : {
    "bool" : {
      "must" : [
        { "terms" : { "Product.ProductID" : [] } }
      ]
    }
  }
}

If I pass empty array as a parameter, see this:

GET /statistic/_search/template
{
    "template": {
        "id": "test" 
    },
    "params": {
        "ProductIDs": []
    }
}

It works as expected and doesn't generate filter condition as described in my template, because array doesn't have any data in it.

I want this:

GET /statistic/_search/template
{
    "template": {
        "id": "test" 
    },
    "params": {
    }
}

To work same as this:

GET /statistic/_search/template
{
    "template": {
        "id": "test" 
    },
    "params": {
        "ProductIDs": []
    }
}

Solution

  • A workaround probably not the most elegant would be to change template query to be a should clause and add a match_all clause for empty list.

    example:

    {
        "filter" : { 
            "bool" : {
                "should" : [  
                    { "terms" : { "status" : [ "{{#ProductIDs}}","{{.}}","{{/ProductIDs}}"] }} 
                    {{^ProductIDs}},
                    {"match_all":{}}
                    {{/ProductIDs}}
                ]
            }
        }
    }