Elasticsearch - как сделать свертывание полей и получить отличные результаты? (фактические записи, а не только счетчики)
В реляционной базе данных наши данные выглядят так: Компания -> Отдел -> Офис
Elasticsearch версия тех же данных (уплощенная):
{
"officeID": 123,
"officeName": "office 1",
"state": "CA",
"department": {
"departmentID": 456,
"departmentName": "Department 1",
"company": {
"companyID": 789,
"companyName": "Company 1",
}
}
},{
"officeID": 124,
"officeName": "office 2",
"state": "CA",
"department": {
"departmentID": 456,
"departmentName": "Department 1",
"company": {
"companyID": 789,
"companyName": "Company 1",
}
}}
Нам нужно найти отдел (или компанию), предоставив служебную информацию (например, штат).
Например, поскольку все, что мне нужно, это информация об отделе, я могу указать ее следующим образом (мы используем Nest)
searchDescriptor = searchDescriptor.Source(x => x.Include("department"));
и получить все отделы с квалификационными отделениями.
Проблема в том, что я получаю несколько записей "отделов" с одним и тем же идентификатором (по одной для каждого офиса).
Мы используем пейджинг и сортировку.
Можно ли получить разбитые на страницы и отсортированные результаты?
Я потратил несколько дней, пытаясь найти ответ (исследуя варианты, такие как фасеты, агрегаты, top_hits и т. Д.), Но пока единственная рабочая опция, которую я вижу, это ручная - получить результаты из Elasticsearch, сгруппировать данные вручную и передать клиенту, Проблема с этим подходом очевидна - каждый раз, когда я беру следующую порцию, мне придется получать X дополнительных записей на тот случай, если некоторые записи будут повторяться; поскольку я заранее не знаю X (а количество таких записей может быть огромным), меня будут вынуждены либо получать много данных без необходимости (каждый раз, когда я выполняю поиск), либо несколько раз попадать в нашу поисковую систему, пока я не получу требуемое число записей.
До сих пор мне не удавалось достичь своей цели с помощью агрегации (все, что я получаю, это количество документов, но мне нужны реальные данные; когда я пытаюсь использовать top_hits, я получаю данные, но это действительно самые популярные запросы (отсортированные по количеству офисов). на отдел, игнорируя сортировку, которую я указал в запросе), вот пример кода, который я пробовал:
searchDescriptor = searchDescriptor.Aggregations(a => a
.Terms("myunique",
t =>
t.Field("department.departmentID")
.Size(10)
.Aggregations(
x=>x.TopHits("mytophits",
y=>y.Source(true)
.Size(1)
.Sort(k => k.OnField("department.departmentName").Ascending())
)
)
)
);
Кто-нибудь знает, может ли Elasticsearch выполнять такие операции, как Distinct, и получать уникальные записи?
Обновление: я могу получить результаты, используя top_hits (см. Ниже), но в этом случае я не смогу использовать пейджинг (похоже, функция агрегации Elasticsearch не поддерживает пейджинг), поэтому я вернулся к исходной точке...
{
"from": 0,
"size": 33,
"explain": false,
"sort": [
{
"departmentID": {
"order": "asc"
}
}
],
"_source": {
"include": [
"department"
]
},
"aggs": {
"myunique": {
"terms": {
"field": "department.departmentID",
"order": {
"mytopscore": "desc"
}
},
"aggs": {
"mytophits": {
"top_hits": {
"size": 5,
"_source": {
"include": [
"department.departmentID"
]
}
}
},
"mytopscore": {
"max": {
"script": "_score"
}
}
}
}
},
"query": {
"wildcard" : { "officeName" : "some office*" }
}
}