Агрегации Elasticsearch — ИЛИ в сегментах

#elasticsearch #elasticsearch-aggregation

#elasticsearch #elasticsearch-агрегация

Вопрос:

Допустим, у меня есть 5 документов:

 {
  "owner": "joe",
  "color": "black"
},
{
  "owner": "joe",
  "color": "red"
},
{
  "owner": "joe",
  "color": "blue"
},
{
  "owner": "jack",
  "color": "black"
},
{
  "owner": "jack",
  "color": "white"
}
 

и агрегации:

 {
  aggs: {
    owner: {
      "terms": {
        "field": "owner"
      }
    },
    color: {
      "terms": {
        "field": "color"
      }
    }
  }
}
 

для агрегирования документов по владельцу и цвету.

Если я выполню сопоставление всех запросов, которые я получил:

 owner
joe: 3
jack: 2

color
black: 2
red: 1
blue: 1
white: 1
 

Чего я хочу добиться: если я фильтрую документы по owner: joe , я хочу получить 3 документа, где owner находится joe агрегация цветов:

 color
black: 1
red: 1
blue: 1
 

НО я хотел бы получить owner агрегацию:

 owner
joe: 3 [selected]
jack: 2 [possible to extend]
 

Итак, получите количество других сегментов, которые можно выбрать для расширения конечного результата. Итак, что-то вроде «ИЛИ» между сегментами.

Как я могу этого добиться?

Ответ №1:

Обычный способ добиться этого — использовать post_filter . Приведенный ниже запрос вернет:

  • только joe цвета (с использованием filtered_colors )
  • только joe документы (с использованием post_filter )
  • все владельцы, по которым вы можете фильтровать (используя all_owners )

Запрос:

 POST owners/_search
{
  "aggs": {
    "filtered_colors": {
      "filter": {
        "term": {
          "owner.keyword": "joe"
        }
      },
      "aggs": {
        "color": {
          "terms": {
            "field": "color.keyword"
          }
        }
      }
    },
    "all_owners": {
      "terms": {
        "field": "owner.keyword"
      }
    }
  },
  "post_filter": {
    "term": {
      "owner.keyword": "joe"
    }
  }
}
 

Комментарии:

1. да, именно так, просто хотел это написать 🙂 спасибо за помощь, ребята!

2. Потрясающе, рад, что это помогло 😉

Ответ №2:

Насколько я могу понять, вы хотите агрегировать owner , а также color (где owner равно joe ) Вы можете использовать агрегацию фильтров для достижения требуемого варианта использования —

     {
      "size": 0,
      "aggs": {
        "owner": {
          "terms": {
            "field": "owner.keyword"
          }
        },
        "filtered_aggregation": {
          "filter": {
            "term": {
              "owner": "joe"
            }
          },
          "aggs": {
            "color": {
              "terms": {
                "field": "color.keyword"
              }
            }
          }
        }
      }
    }
 

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

     "aggregations": {
        "owner": {
          "doc_count_error_upper_bound": 0,
          "sum_other_doc_count": 0,
          "buckets": [
            {
              "key": "joe",
              "doc_count": 3
            },
            {
              "key": "jack",
              "doc_count": 2
            }
          ]
        },
        "filtered_aggregation": {
          "doc_count": 3,
          "color": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
              {
                "key": "black",
                "doc_count": 1
              },
              {
                "key": "blue",
                "doc_count": 1
              },
              {
                "key": "red",
                "doc_count": 1
              }
            ]
          }
        }
      }
 

Комментарии:

1. Я не уверен, что это удовлетворяет ограничению I want to get 3 docs where owner is joe