Вопрос или проблема
У меня есть функция агрегации mongo, которая подсчитывает количество документов по группировке некоторых полей. И на самом деле мне нужно только число в качестве идентификатора и поле с количеством, как у меня уже есть.
Но также мне нужно выполнить $sort и $match в моей функции агрегации, но из-за того, что у моего документа всего 2 поля после группировки, я предполагаю, что $sort и $match не работают.
Как я могу сначала выполнить sort
и match
, а затем сделать group by
?
Моя функция агрегации:
db.collection.aggregate([
{
"$sort": {
"updated_at": -1
}
},
{
"$match": {
"user": "aboba"
}
},
{
"$group": {
"_id": {
"number": "$number",
"user": "$user"
}
}
},
{
"$group": {
"_id": "$_id.user",
"count": {
"$sum": 1
}
}
},
{
"$unwind": "$_id"
}
])
В моей функции агрегации я точно могу сказать, что сортировка по обновленной дате совсем не работает.
Ответ или решение
Чтобы правильно использовать операции $match
и $sort
перед группировкой ($group
) в MongoDB, необходимо учесть порядок выполнения стадий агрегации. Операции агрегации выполняются последовательно, и Каждый последующий этап работает с результатами предыдущего. Важно помнить, что после применения $group
мы не можем использовать первичные поля документа, которые были сгруппированы, в стадии $sort
или $match
, потому что на этом этапе этих полей больше нет.
Давайте разберемся, как правильно перестроить ваш запрос, чтобы операции $sort
и $match
работали должным образом до группировки.
-
Сначала используем
$match
, чтобы отфильтровать документы. Это позволяет сократить объем данных, которые будут обработаны на следующих этапах, и тем самым улучшить производительность агрегации. -
Затем применяем
$sort
, чтобы отсортировать отфильтрованные документы. -
После этого можем использовать
$group
, чтобы подсчитать количество документов по нужным полям.
Вот как должен выглядеть ваш агрегационный запрос:
db.collection.aggregate([
{
"$match": {
"user": "aboba"
}
},
{
"$sort": {
"updated_at": -1
}
},
{
"$group": {
"_id": {
"number": "$number",
"user": "$user"
}
}
},
{
"$group": {
"_id": "$_id.user",
"count": {
"$sum": 1
}
}
},
{
"$unwind": "$_id"
}
])
Объяснение:
-
"$match"
сначала отфильтрует все документы, оставив лишь те, у которых полеuser
равно "aboba". Это уменьшает количество документов, которые будут обрабатываться на следующих этапах. -
"$sort"
выполнит сортировку оставшихся документов по полюupdated_at
в порядке убывания. -
Затем с помощью
"$group"
вы сгруппируете документы по полямnumber
иuser
. -
После этого еще один
$group
подсчитает количество документов для каждого уникального пользователя. -
Наконец,
$unwind
распакует массив, если он есть, хотя этот этап может быть не нужен в зависимости от вашего конечного формата.
Используя данный порядок стадий, вы сможете успешно выполнить операции $match
, $sort
и $group
, как требуется.