Elasticsearch Mustache可选参数

时间:2015-08-26 06:24:51

标签: java templates elasticsearch mustache elasticsearch-template

我一直在努力使用Elasticsearch模板,特别是在可选参数中。我想在那里添加可选过滤器。这是我尝试的代码片段:

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

当然,我将"替换为\",将其更新,并将其包裹在{ "template" :"_snippet_above_" }中。

现在,当我尝试使用以下内容调用它时:

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

它忽略了我提供的参数,但是当我尝试在官方的mustache.io演示页面中这样做时 - 它的工作正常。

我也尝试了{{#ProductIDs.length}}选项 - 它没有成功。在做了一些研究之后,我发现 mustache.js mustache.java 之间存在一个区别。我假设Elasticsearch使用JAVA版本并且它不支持长度参数,所以我必须依赖isEmpty。所以我按如下方式重写了我的查询:

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

现在,当我使用ProductIDs列表查询模板时 - 它工作正常,但是如果我删除参数,它不会带来任何结果。我认为它会产生这个:

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

如果我将空数组作为参数发送 - 它工作正常。

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

我认为这是因为"ProductIDs"undefined而非空。

有没有办法在mustache.java中使用这个条件,所以我可以忽略这些参数?

TL;博士; 问题是,如果我没有通过模板在搜索请求中指定参数,我的条件将呈现为空数组,请参阅:

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

如果我将空数组作为参数传递,请参阅:

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

它按预期工作,并且不会生成我的模板中描述的过滤条件,因为数组中没有任何数据。

我想要这个:

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

与此相同:

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

2 个答案:

答案 0 :(得分:2)

可能不是最优雅的解决方法是将模板查询更改为should子句并为空列表添加match_all子句。

示例:

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

答案 1 :(得分:1)

我建议使用JSON模板克服此问​​题的建议是

{
   "query": {
      "bool": {
        "must": [
            {
                "script": {
                    "script": {
                        "inline": "1==1 {{#ProductIDs}} &&  [\"{{#ProductIDs}}\",\"{{.}}\",\"{{/ProductIDs}}\"].contains(doc['Product.ProductID'].value){{/ProductIDs}}",
                        "lang": "painless"
                    }
                }
            }
        ]
    }
}