Как объединить запрос с несколькими терминами в фильтре Elasticsearch

В настоящее время я ищу фильтр Elasticsearch (для моего запроса) для фильтрации моего запроса, но он не работает, потому что фильтр также не фильтрует.

Версия кластера ES - 6.8.3. Вот мой текущий код фильтра (версия PHP):

'filter' => [
     ['term' => 
            [
                                'displayMode' => 'hidden'
                            ]],
                            [ 'bool' => [
                                'must_not' => [
                                    [ 'bool' => [
                                        'must' => [
                                            'term' => ['displayMode' => 'untreated']
                                        ]
                                    ]],
                                    [ 'bool' => [
                                        'must' => [
                                            'term' => [ 'lifetime' => 'temporary' ]
                                        ]
                                    ]]
                                ]]
                            ],
                            [ 'bool' => [
                                'must' => [
                                    [ 'bool' => [
                                        'must_not' => [
                                            'term' => ['activity' => 'inactive']
                                        ]
                                    ]],
                                    [ 'bool' => [
                                        'must_not' => [
                                            'term' => [ 'lifetime' => 'everlasting' ]
                                        ]
                                    ]],
                                    [ 'bool' => [
                                        'should' => [
                                            [ 'range' => [
                                                'toDate' => [
                                                    'lt' => (new \DateTime())->format('Y-m-d')
                                                ]
                                            ]],
                                            [ 'bool' => [
                                                'must_not' => [
                                                    'exists' => [
                                                        'field' => 'toDate'
                                                    ]
                                                ]
                                            ]]
                                        ]
                                    ]]
                                ]
                            ]]
      ]

Итак, чтобы отобразить элемент, вы должны соблюдать все эти условия:

item.displayAll != 'hidden'

А ТАКЖЕ

(item.displayMode != 'untreated' AND item.lifetime != 'temporary')

А ТАКЖЕ

(item.activity != 'inactive' AND item.lifetime != 'everlasting' AND item.toDate < NOW())

К сожалению, мои "многосторонние" условия не являются множественными, поэтому кажется, что каждый из вспомогательных фильтров выполняется один за другим. Поэтому, если мой элемент "необработан", но его "время жизни" отличается от "временного", элемент фильтруется, но этого не должно быть.

РЕДАКТИРОВАТЬ: Когда я пытаюсь упростить свой фильтр (просто чтобы проверить, работает ли маленький), он тоже не работает...

// ...
'filter' => [
                                ['bool' => [
                                    'must_not' => [
                                        ['term' => [ 'displayMode' => 'untreated' ]],
                                        ['term' => [ 'lifetime' => 'temporary' ]]
                                    ]
                                ]],
   // ...

ИЛИ

'filter' => [
                                ['bool' => [
                                    'must' => [
                                        ['bool' => [
                                            'must_not' => [
                                                ['term' => [ 'displayMode' => 'untreated' ]],
                                            ]
                                        ]],
                                        ['bool' => [
                                            'must_not' => [
                                                ['term' => [ 'lifetime' => 'temporary' ]]
                                            ]
                                        ]]
                                    ]
                                ]],

(два приведенных выше примера не работают, потому что они фильтруют все результаты, даже действительные)

ИЛИ

'filter' => [
                                ['bool' => [
                                    'should' => [
                                        ['bool' => [
                                            'must_not' => [
                                                ['term' => [ 'displayMode' => 'untreated' ]],
                                            ]
                                        ]],
                                        ['bool' => [
                                            'must_not' => [
                                                ['term' => [ 'lifetime' => 'temporary' ]]
                                            ]
                                        ]]
                                    ]
                                ]],

(Пример выше, он не фильтрует ничего, как я хотел).

ИЛИ

'filter' => [
                                ['bool' => [
                                    'must_not' => [
                                        ['term' => [ 'displayMode' => 'untreated' ]],
                                        ['term' => [ 'lifetime' => 'temporary' ]]
                                    ]
                                ]]

То же, он фильтрует все результаты..

Кто-нибудь может мне помочь?

2 ответа

Итак, согласно вашей логической логике, вы можете просто преобразовать это в bool запросы:

  • AND => filter
  • OR => should
  • != => must_not

Это даст следующее:

{
  "query": {
    "bool": {
      "minimum_should_match": 1,
      "should": [
        {
          "bool": {
            "must_not": {
              "term": {
                "displayMode": "hidden"
              }
            }
          }
        },
        {
          "bool": {
            "must_not": [
              {
                "term": {
                  "displayMode": "untreated"
                }
              },
              {
                "term": {
                  "lifetime": "temporary"
                }
              }
            ]
          }
        },
        {
          "bool": {
            "must_not": [
              {
                "term": {
                  "activity": "inactive"
                }
              },
              {
                "term": {
                  "lifetime": "everlasting"
                }
              },
              {
                "bool": {
                  "should": [
                    {
                      "range": {
                        "toDate": {
                          "lt": "now"
                        }
                      }
                    },
                    {
                      "bool": {
                        "must_not": {
                          "exists": {
                            "field": "toDate"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            ]
          }
        }
      ]
    }
  }
}

Итак, после огромной траты времени я наконец понял, что мой индекс не содержит поля "время жизни". Для этого не выполнялись все условия фильтров. Мой первый запрос был хорошим (или одним из способов сделать то, что я хотел). Хорошего дня.

Другие вопросы по тегам