0

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

1 Answers1

2

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
              }
            }
          ]
        }
        }

    ]
  }
}
Polynomial Proton
  • 5,020
  • 20
  • 37
  • Thanks for that .. but in your scenario .. you are considering only object for the should array .. but i will need to give 100 objects to the should array .. and each out of those will have the 3 term filters #polynomilProton @polynomialProton – Praveen Sureshkumar Oct 08 '19 at 21:01
  • Your edited answer works .. Thanks a lot, I did try giving array of objects to clauses but missed a '{' or two when i was directly escaping \" instead of using """{"query"}""" .. Thanks a lot for that – Praveen Sureshkumar Oct 09 '19 at 07:09