Необязательные параметры Elasticsearch Moustache

Я боролся с шаблонами 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; dr; Проблема в том, что если я не укажу параметр в моем поисковом запросе через шаблон, мое условие будет отображаться как пустой массив, см. это:

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

person Evaldas Buinauskas    schedule 26.08.2015    source источник
comment
Я не понимаю, в чем проблема и чего ожидать.   -  person Andrei Stefan    schedule 08.09.2015
comment
Извините за путаницу, @AndreiStefan, я обновил вопрос. Дайте мне знать, есть ли в этом смысл сейчас.   -  person Evaldas Buinauskas    schedule 08.09.2015


Ответы (3)


Обходной путь, вероятно, не самый элегантный, - это изменить запрос шаблона на предложение should и добавить предложение match_all для пустого списка.

пример:

{
    "filter" : { 
        "bool" : {
            "should" : [  
                { "terms" : { "status" : [ "{{#ProductIDs}}","{{.}}","{{/ProductIDs}}"] }} 
                {{^ProductIDs}},
                {"match_all":{}}
                {{/ProductIDs}}
            ]
        }
    }
}
person keety    schedule 09.09.2015
comment
Что ж, это обходной путь, о котором я думал. Но меня интересует реальное решение. Если я не передаю какой-либо параметр - вообще не рендерить. :( - person Evaldas Buinauskas; 10.09.2015
comment
учитывая, что mustache.java не поддерживает доступ к элементам массива, я не думаю, что есть способ обойти это, но реструктурировать свой шаблонный запрос, как указано выше, или использовать дополнительный параметр, который имеет длину списка, и использовать его в качестве условного для введения предложения must - person keety; 10.09.2015
comment
Меня интересует только проверка, существует ли данный параметр или не пуст. Кажется, что передача пустого массива / списка - это единственное решение, не так ли? - person Evaldas Buinauskas; 10.09.2015
comment
да, правда, это тоже работает, однако, если вы хотите получить результат, когда ProductsID не передается, вам потребуется обходной путь изменения запроса или использования параметра флага - person keety; 10.09.2015

Не пробовал, но не должно ли что-то вроде этого работать?

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

Некрасиво, может быть, есть способ получше.

person slawek    schedule 10.09.2015

Мое предложение преодолеть это с помощью шаблона JSON:

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