templateselasticsearchmustacheelasticsearch-aggregationelasticsearch-template

Search Template in Elastic for filter and should


I am setting up a search template to get a list of bool filters within a bool should query. I have 3 fields on es [A,B,C]. The query should return back buckets of combination of these three fields. i should be able to give [a1,b1,c1] [a2,b2,c2] ... [an,bn,cn] as params to the template

I tried creating a template that has a should query with a {{#toJson}}clauses{{/toJson}} to create the inner term filter objects like

"clauses":[
{"term": {"fieldA": 30}},
{"term": {"fieldB": 0}},
{"term": {"fieldC": 1}}
]

I was hoping to have a section around it inside the "should" : [{{#shouldBlock}}{{#toJson}}clauses{{/toJson}}{{/ShouldBlock}}]

is there any way to have like a filter inside the should that takes the "toJson"

Like

"bool":{
"should":[
{
          // this loops for 100 times   
          "bool":{
                  "filter":[
                          {term for fieldA},
                          {term for fieldB},  // three terms for three fields
                          {term for fieldC}
                           ] 
                 }
          // end of loop
}
]

This is my query. and this is expected as a response for the render

GET adn/_search
{
  "size": 10,
  "query": {
       "bool": {
         "minimum_should_match": 1, 
         "should": [
           {
             "bool": {
               "filter": [
                 {"term": {"fieldA": 30}},
                 {"term": {"fieldB": 0}},
                 {"term": {"fieldC": 1}}
               ]
           }
          },
            {
             "bool": {
               "filter": [
                 {"term": {"fieldA": 0}},
                 {"term": {"fieldB": 1}},
                 {"term": {"fieldC": 0}}
               ]
           }
          }
         ]
       }
     }
}

My first try was to add the inside condition for should as text inside a section

GET _render/template
{
    "source": "{\"query\": {\"bool\": {\"should\":[ {{#section}} {\"bool\":{\"filter\": {{#toJson}}clauses{{/toJson}} } } {{/section}} }}}",
    "params": {
      "section":{
        "shouldBlock":[]
      },
      "clauses": [
            { "term": { "breakId" : 1 } },
            { "term": { "offset" : 0 } }
        ]

    }
}

that gave an error

{
  "error": {
    "root_cause": [
      {
        "type": "json_parse_exception",
        "reason": "Unexpected close marker '}': expected ']' (for Array starting at [Source: org.elasticsearch.common.bytes.BytesReference$MarkSupportingStreamInputWrapper@5a909404; line: 1, column: 30])\n at [Source: org.elasticsearch.common.bytes.BytesReference$MarkSupportingStreamInputWrapper@5a909404; line: 1, column: 102]"
      }
    ],
    "type": "json_parse_exception",
    "reason": "Unexpected close marker '}': expected ']' (for Array starting at [Source: org.elasticsearch.common.bytes.BytesReference$MarkSupportingStreamInputWrapper@5a909404; line: 1, column: 30])\n at [Source: org.elasticsearch.common.bytes.BytesReference$MarkSupportingStreamInputWrapper@5a909404; line: 1, column: 102]"
  },
  "status": 500
}

I tried some thing like a section with a param to hold

GET _render/template
{
    "source": "{\"query\": {\"bool\": {\"should\":[ {{#section}} {{shouldBlock}} {{#toJson}}clauses{{/toJson}} }] {{/section}} } } }",
    "params": {
      "clauses": [
            { "term": { "fieldA" : 1 } },
            { "term": { "fieldB" : 0 } }
        ]

    }
}

Things I had to keep in mind. section that loops : 100 times

"bool":{
       "filter":[
                 {"term": {"fieldA": a1}},
                 {"term": {"fieldB": b1}},
                 {"term": {"fieldC": c1}},
                ]
}

Each one object of the above 100 has a a different filter block with combination of 3fields with different values for those 3 fields [fieldA,fieldB,fieldC]

I read that the array for "filter" can be achieved by the 'toJson' function of elastic search but the outer part of it is difficult for me to decipher

It would be great if some one could help me out


Solution

  • Your query is not correct. Once you fix that it should work:

    render template

    Here's the one that works:

    GET _render/template
    {
      "source": """{
      "query": {
        "bool": {
          {{#section}}
          "should": [
            {
              "bool": {
                "filter": [
                  {{#toJson}}clauses{{/toJson}}
                  ]
              }
            }
          ]
          {{/section}}
        }
      }
    }""",
      "params": {
        "section":true, 
        "clauses": [
          {
            "term": {
              "fieldA": 1
            }
          },
          {
            "term": {
              "fieldB": 0
            }
          }
        ]
      }
    }
    

    Edit based on comment:


    All your queries will then be part of the request parameters. mustache is logic-less templates so you cannot have if-else or loops

    GET _render/template
    {
      "source": """
    {
      "query": {
        "bool": {
          {{#section}}
          "should": {{#toJson}}clauses{{/toJson}}
          {{/section}}
        }
      }
    }
    """,
      "params": {
      "section":true,
        "clauses": [
          {
            "bool": {
              "filter": [
                {
                  "term": {
                    "fieldA": 1
                  }
                },
                {
                  "term": {
                    "fieldB": 0
                  }
                }
              ]
            }
          },
            {
              "bool": {
              "filter": [
                {
                  "term": {
                    "fieldA": 1
                  }
                },
                {
                  "term": {
                    "fieldB": 0
                  }
                }
              ]
            }
            },
            {
              "bool": {
              "filter": [
                {
                  "term": {
                    "fieldA": 1
                  }
                },
                {
                  "term": {
                    "fieldB": 0
                  }
                }
              ]
            }
            }
    
        ]
      }
    }