Удалите выбранные фильтры из вложенных и агрегированных в Elasticsearch, чтобы выполнить фильтрованный поиск.

Я пытаюсь использовать elasticsearch (ВЕРСИЯ 7.8.0) для выполнения многогранного поиска, и у меня что-то получилось. Однако я хочу удалить выбранные фильтры из моих возвращенных агрегатов. Например. Если у меня есть магазин по продаже одежды, и я фильтрую товары по цвету: красный, то я не хочу, чтобы цвет: красный появлялся в моих агрегатах, так как он уже выбран.

Для выполнения моих фильтров у меня есть следующее вложенное поле в моих примерах продуктов:

"search_filters" : {
    "type" : "nested",
    "properties" : {
        "key" : {
          "type" : "keyword"
        },
        "value" : {
          "type" : "keyword"
        }
     }
 },

Итак, если бы у меня были данные вроде

 "search_filters" : [
     {
         "key" : "colour",
         "value" : "red"
     }
 ]

Затем я выполняю поиск, например:

  {
  "query": {
    "bool": {
      "must": [
        {
          "nested": {
            "path": "search_filters",
            "query": {
              "bool": {
                "must": [
                  {
                    "match": {
                      "search_filters.key": "colour"
                    }
                  },
                  {
                    "match": {
                      "search_filters.value": "red"
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  },
  "aggs": {
    "filters": {
      "nested": {
        "path": "search_filters"
      },
      "aggs": {
        "search_keys": {
          "terms": {
            "field": "search_filters.key"
          },
          "aggs": {
            "search_values": {
              "terms": {
                "field": "search_filters.value"
              }
            }
          }
        }
      }
    }
  }
}

Это дает мне правильные документы, но мои агрегаты показывают цвет: красный.

{
  ...
  "filters": {
    "doc_count": 31,
    "search_keys": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "colour",
          "doc_count": 31,
          "search_values": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
              {
                "key": "red",
                "doc_count": 31
              }
              ...
            ]
          }
        }
        ...
      ]
    }
  }
}

Есть ли способ исключить их из elasticsearch или мне нужно вручную анализировать и игнорировать/удалять выбранные фильтры?

Я видел использование фильтра в части поля агрегации запроса, но не смог заставить его работать с моим полем фильтра; особенно когда я применил более одного фильтра, например. цвет и размер.


person PanPipes    schedule 16.02.2021    source источник
comment
Вы хотите исключить те результаты, которые имеют "search_filters.value": "red"?   -  person ESCoder    schedule 16.02.2021
comment
Я хочу продукты, которые имеют красный цвет в моих возвращенных документах. Однако я хочу, чтобы elasticsearch не включал это в агрегации. В основном агрегация не знает, что я уже отфильтровал документы по красному, если это имеет смысл. Честно говоря, это может быть невозможно, или, может быть, я использую совершенно неправильные параметры; Точно сказать не могу. Спасибо   -  person PanPipes    schedule 16.02.2021


Ответы (1)


Вы можете использовать агрегацию фильтров, чтобы исключить те результаты, которые соответствуют "search_filters.key": "colour" "search_filters.value": "red". Это может содержать дополнительные обязательные элементы для дополнительных фильтров.

{
  "query": {
    "nested": {
      "path": "search_filters",
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "search_filters.key": "colour"
              }
            },
            {
              "match": {
                "search_filters.value": "red"
              }
            }
          ]
        }
      }
    }
  },
  "aggs": {
    "filters": {
      "nested": {
        "path": "search_filters"
      },
      "aggs": {
        "filterResult": {
          "filter": {
            "bool": {
              "must_not": {
                {
                  "bool": {
                    "must": [
                      {
                        "match": {
                          "search_filters.key": "colour"
                        }
                      },
                      {
                        "match": {
                          "search_filters.value": "red"
                      }
                    }
                  ]
                }
              }
            }
          },
          "aggs": {
            "search_keys": {
              "terms": {
                "field": "search_filters.key"
              },
              "aggs": {
                "search_values": {
                  "terms": {
                    "field": "search_filters.value"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

Результат поиска будет

"hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0.8754687,
    "hits": [
      {
        "_index": "66222818",
        "_type": "_doc",
        "_id": "1",
        "_score": 0.8754687,
        "_source": {
          "search_filters": [
            {
              "key": "colour",
              "value": "red"                 // note this
            }
          ]
        }
      }
    ]
  },
  "aggregations": {
    "filters": {
      "doc_count": 1,
      "filterResult": {
        "doc_count": 0,
        "search_keys": {
          "doc_count_error_upper_bound": 0,
          "sum_other_doc_count": 0,
          "buckets": []                                // note this
        } 
      }
    }
  }
person ESCoder    schedule 16.02.2021
comment
@PanPipes, могу я узнать, почему у вас не работает агрегация фильтров? - person ESCoder; 16.02.2021
comment
Хорошо, я думаю, что я не использовал filterResult и просто пытался добавить фильтр на уровень выше. Позвольте мне попробовать описанное выше с другими фильтрами и посмотреть, что произойдет. Спасибо - person PanPipes; 16.02.2021
comment
Хорошо, так что это близко и в правильном направлении, спасибо. Однако, если сказать, что у меня есть другой фильтр с другим ключом, но с тем же значением. Например. цвет выделения: красный, я потеряю эту информацию в агрегации. Есть идеи? Я думаю, что это то, где я застрял раньше, поэтому делать это обязательно, а не с AND - person PanPipes; 16.02.2021
comment
@PanPipes, не могли бы вы объяснить на примере, чтобы мне было легче воспроизвести проблему? - person ESCoder; 16.02.2021
comment
Не волнуйтесь, я решил это, используя дополнительный уровень bool и musts внутри must_not. Так что спасибо, ваш ответ привел меня туда, куда мне нужно было идти! - person PanPipes; 16.02.2021
comment
Я немного отредактировал ваш ответ, чтобы он соответствовал моим требованиям. Надеюсь, изменение поможет объяснить, но еще раз спасибо за вашу помощь, это было очень ценно. - person PanPipes; 16.02.2021