Я новичок в ElasticSearch и пытаюсь объединить объекты, полученные в результате поиска, по иерархическим категориям.
Я заранее прошу прощения за длину вопроса, но я хотел дать достаточное количество образцов и информации, чтобы сделать потребность как можно более ясной.
Что я пытаюсь достичь
Проблема в том, что категории образуют иерархию, но представлены в виде плоского массива объектов, каждый из которых имеет глубину. Я хотел бы создать агрегацию, которая бы разбивалась по категориям и по глубине категории.
Вот упрощенное отображение документа, который содержит только минимальные данные:
{
"mappings": {
"_doc": {
"properties": {
"categoriesList": {
"properties": {
"depth": {
"type": "long"
},
"title": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
}
}
Вот упрощенный образец документа:
{
"_index": "x",
"_type": "_doc",
"_id": "wY0w5GYBOIOl7fi31c_b",
"_score": 22.72073,
"_source": {
"categoriesList": [
{
"title": "category_lvl_2_2",
"depth": 2
},
{
"title": "category_lvl_2",
"depth": 2,
},
{
"title": "category_lvl_1",
"depth": 1
}
]
}
}
Теперь я пытаюсь получить иерархические сегменты категорий на основе их глубины, т. Е. Я хочу иметь блок, содержащий все заголовки категорий глубины 1 по всем попаданиям, а затем другой блок (или вложенный сегмент) с названиями только категорий глубины 2 для всех хитов и так далее.
Что-то вроде:
"aggregations": {
"depth": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 1,
"doc_count": 47,
"name": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "category_lvl_1",
"doc_count": 47,
"depth_1": {
"doc_count": 47
}
}
]
}
},
{
"key": 2,
"doc_count": 47,
"name": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "category_lvl_2_1",
"doc_count": 47
},
{
"key": "category_lvl_2_2",
"doc_count": 33
}
]
}
}
]
}
}
Что я пробовал
Сначала я попытался просто создать вложенные агрегаты следующим образом:
"aggs": {
"depth": {
"terms": {
"field": "categoriesList.depth"
},
"aggs": {
"name": {
"terms": {
"field": "categoriesList.title.keyword"
},
}
}
}
}
Это, конечно, не дало то, что я хотел. Это в основном дало мне ведра, ключи которых были по глубине, но в них были все названия всех категорий, независимо от их глубины; содержимое было одинаковым. Примерно так:
"aggregations": {
"depth": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 1,
"doc_count": 47,
"name": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "category_lvl_1",
"doc_count": 47
},
{
"key": "category_lvl_2_1",
"doc_count": 33
},
{
"key": "category_lvl_2_2",
"doc_count": 15
}
]
}
},
{
"key": 2,
"doc_count": 47,
"name": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "category_lvl_1",
"doc_count": 47
},
{
"key": "category_lvl_2_1",
"doc_count": 33
},
{
"key": "category_lvl_2_2",
"doc_count": 15
}
]
}
}
]
}
}
Затем я попытался посмотреть, сработает ли отфильтрованная агрегация, попытавшись отфильтровать одно вложенное ведро по значению глубины 1:
"aggs": {
"depth": {
"terms": {
"field": "categoriesList.depth"
},
"aggs": {
"name": {
"terms": {
"field": "categoriesList.title.keyword"
},
"aggs": {
"depth_1": {
"filter": {
"term": {
"categoriesList.depth": 1
}
}
}
}
}
}
}
}
Это дало те же результаты, что и простой запрос агрегации выше, но с дополнительным уровнем вложенности, который не имел смысла.
Вопрос
С моим текущим пониманием ES, то, что я вижу, имеет смысл: оно просматривает каждый документ из поиска и затем создает сегменты на основе глубины категории, но, поскольку каждый документ имеет по крайней мере одну категорию с каждой глубиной, весь список категорий добавлен в корзину.
Возможно ли то, что я пытаюсь сделать с помощью ES? У меня такое ощущение, что это не сработает, потому что я в основном пытаюсь создать и отфильтровать свойства, использованные в исходном запросе, а не работать со свойствами документа.
Я мог бы также включить себя непосредственно в код, так как мы получаем результаты по категориям, но я хотел знать, возможно ли это сделать на стороне ES, что избавило бы меня от изменения существующего кода, который у нас есть.
Спасибо!