4

我一直在努力使用 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.jsmustache.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": []
    }
}
4

3 回答 3

3

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

例子:

{
    "filter" : { 
        "bool" : {
            "should" : [  
                { "terms" : { "status" : [ "{{#ProductIDs}}","{{.}}","{{/ProductIDs}}"] }} 
                {{^ProductIDs}},
                {"match_all":{}}
                {{/ProductIDs}}
            ]
        }
    }
}
于 2015-09-09T15:34:06.283 回答
1

没试过,但不应该这样的工作吗?

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

不漂亮,也许有更好的方法。

于 2015-09-10T13:33:41.260 回答
1

我使用 JSON 模板克服这个问题的建议是:

{
   "query": {
      "bool": {
        "must": [
            {
                "script": {
                    "script": {
                        "inline": "1==1 {{#ProductIDs}} &&  [\"{{#ProductIDs}}\",\"{{.}}\",\"{{/ProductIDs}}\"].contains(doc['Product.ProductID'].value){{/ProductIDs}}",
                        "lang": "painless"
                    }
                }
            }
        ]
    }
}
于 2019-10-11T13:46:42.147 回答