elasticsearchdate-rangeelasticsearch-template

Date Range Query using SearchTemplate in Elasticsearch with Should clause


We have a scenario where we have to do range query with "OR" condition. It is working fine, with one query, but getting error while triggering with multiple query.

POST _scripts/dateTemplate
{
  "script": {
    "lang": "mustache",
    "source": """
        {
        "query": {
            "bool": {
                "must": {
                "query_string": {
                    "query": "title:({{searchkeyword}})"
                }
            },
            "filter": {
                "bool":{
                    "must":[
                        {
                            "match_all": {}
                        }
                        {{#f_url}} , {
                            "terms" : {
                                "f_url": [{{#toJson}}f_url{{/toJson}} ]
                                }
                            }
                        {{/f_url}}
                    ],
                    "should":[
                        {{#since}}
                            {
                                "range": {
                                    "{{since}}": {
                                        {{#from}}"from": "{{from}}"{{#to}},{{/to}}{{/from}}
                                        {{#to}}"to":"{{to}}"{{/to}}
                                    }
                                }
                            }
                        {{/since}}
                    ]
                }
            }
        }
    }
    }
"""
  }
}

Query while calling the template

POST _search/template
{
  "id": "dateTemplate",
  "params": {
    "searchkeyword": "*",
    "since":[ {
      "since":"@timestamp",
      "from": "2018-06-01"
    },
     {
      "since":"@timestamp",
      "from": "2018-06-08"
    }
    ]
  }
}

Error

{
  "error": {
    "root_cause": [
      {
        "type": "json_parse_exception",
        "reason": "Unexpected character ('{' (code 123)): was expecting comma to separate Array entries\n at [Source: \t\t{\n\t\t\"query\": {\n\t\t\t\"bool\": {\n\t\t\t\t\"must\": {\n\t\t\t\t\"query_string\": {\n\t\t\t\t\t\"query\": \"title:(*)\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"filter\": {\n\t\t\t\t\"bool\":{\n\t\t\t\t\t\"must\":[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"match_all\": {}\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t\t\t\"should\":[\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\t\t\t\"@timestamp\": {\n\t\t\t\t\t\t\t\t\t\t\"from\": \"2018-06-01\"\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\t\t\t\"@timestamp\": {\n\t\t\t\t\t\t\t\t\t\t\"from\": \"2018-06-08\"\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t}; line: 25, column: 9]"
      }
    ],
    "type": "json_parse_exception",
    "reason": "Unexpected character ('{' (code 123)): was expecting comma to separate Array entries\n at [Source: \t\t{\n\t\t\"query\": {\n\t\t\t\"bool\": {\n\t\t\t\t\"must\": {\n\t\t\t\t\"query_string\": {\n\t\t\t\t\t\"query\": \"title:(*)\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"filter\": {\n\t\t\t\t\"bool\":{\n\t\t\t\t\t\"must\":[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"match_all\": {}\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t\t\t\"should\":[\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\t\t\t\"@timestamp\": {\n\t\t\t\t\t\t\t\t\t\t\"from\": \"2018-06-01\"\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\t\t\t\"@timestamp\": {\n\t\t\t\t\t\t\t\t\t\t\"from\": \"2018-06-08\"\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t}; line: 25, column: 9]"
  },
  "status": 500
}

Same if I add it in must clause, it is working perfectly with "AND" condition. Can you please help in framing the template with both "AND" and "OR" Condition?


Solution

  • You're almost there, you simply need to let mustache know when the last element of the array is reached. So your template should look like this (i.e. we add a comma after each element, except the last one):

      ...
                    "should":[
                        {{#since}}
                            {
                                "range": {
                                    "{{since}}": {
                                        {{#from}}"from": "{{from}}"{{#to}},{{/to}}{{/from}}
                                        {{#to}}"to":"{{to}}"{{/to}}
                                    }
                                }
                            }{{^last}},{{/last}}                <-- modify this line
                        {{/since}}
                    ]
      ...
    

    And then simply modify your call to include the last flag to the last element of the since array:

    POST _search/template
    {
      "id": "dateTemplate",
      "params": {
        "searchkeyword": "*",
        "since":[ {
          "since":"@timestamp",
          "from": "2018-06-01"
        },
         {
          "since":"@timestamp",
          "from": "2018-06-08",
          "last": true                                         <-- add this line
        }
        ]
      }
    }