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": []
}
}
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}}
]
}
}
}