Я использую MongoDB 4.0 в кластере mongoDB Atlas (3 реплики - 1 осколок).
Предполагается, что у меня есть коллекция, содержащая несколько документов.
Каждый из этих документов содержит массив из поддокументов, представляющих города в определенном году с дополнительной информацией. Пример документа будет выглядеть так (я удалил ненужную информацию, чтобы упростить пример):
{_id:123,
cities:[
{name:"vienna",
year:1985
},
{name:"berlin",
year:2001
}
{name:"vienna",
year:1985
}
]}
У меня есть составной индекс по и год. Каков самый быстрый способ подсчета появления комбинаций имени и года?
Я уже пробовал следующую агрегацию:
[{$unwind: {
path: '$cities'
}}, {$group: {
_id: {
name: 'cities.name',
year: '$cities.year'
},
count: {
$sum: 1
}
}}, {$project: {
count: 1,
name: '$_id.name',
year: '$_id.year',
_id: 0
}}]
Другой подход, который я пробовал, - это сокращение карты в следующей форме - уменьшение карты выполняется немного лучше ~ на 30% меньше времени.
функция карты:
function m() {
for (var i in this.cities) {
emit({
name: this.cities[i].name,
year: this.cities[i].year
},
1);
}
}
функция уменьшения (также пытались заменить сумму на длину, но на удивление сумма работает быстрее) :
function r(id, counts) {
return Array.sum(counts);
}
вызов функции в mongoshell:
db.test.mapReduce(m,r,{out:"mr_test"})
Теперь я спрашивал себя - можно ли получить доступ к индексу? Насколько я знаю, это дерево B +, которое содержит указатели на соответствующие документы на диске, поэтому с технической точки зрения, я думаю, можно было бы перебирать все листья дерева индекса и просто подсчитывать указатели? Кто-нибудь, если это возможно?
Кто-нибудь знает другой способ решить этот подход с высокой производительностью? (Невозможно изменить дизайн из-за других зависимостей программного обеспечения, мы запускаем его на очень большом наборе данных). Может быть, у кого-нибудь есть опыт решения такой задачи с помощью шардов?