У меня есть вопрос, который я ожидал бы быть довольно простым, но я не могу понять это. Я хочу сделать следующее:
- Найти все документы в коллекции и:
- отсортировать документы по определенному полю даты
- применить
distinct
водно из его других полей, , но возвращает весь документ
Лучше всего показано в примере.
Это вводный ввод:
[
{
"commandName" : "migration_a",
"executionDate" : ISODate("1998-11-04T18:46:14.000Z")
},
{
"commandName" : "migration_a",
"executionDate" : ISODate("1970-05-09T20:16:37.000Z")
},
{
"commandName" : "migration_a",
"executionDate" : ISODate("2005-11-08T11:58:52.000Z")
},
{
"commandName" : "migration_b",
"executionDate" : ISODate("2016-06-02T19:48:34.000Z")
}
]
Ожидаемый вывод:
[
{
"commandName" : "migration_a",
"executionDate" : ISODate("2005-11-08T11:58:52.000Z")
},
{
"commandName" : "migration_b",
"executionDate" : ISODate("2016-06-02T19:48:34.000Z")
}
]
Или, другими словами:
- Сгруппируйте входные данные по полю
commandName
- Внутри каждой группы Сортируйте документы
- Верните самый новый документ из каждой группы
Мои попытки написать этот запрос потерпели неудачу:
Функция distinct()
будет возвращать только значение поля, по которому я различаюсь,не весь документ. Это делает его непригодным для моего случая.
Пробовал писать запрос aggregate
, но столкнулся с проблемой, как отсортировать и выбрать один документ внутри каждой группы? Стадия агрегации sort
будет сортировать groups
между собой, а это не то, чего я хочу.
Я не слишком хорошо разбираюсь в Монго, и именно здесь я бьюстена. Любые идеи о том, как продолжить?
Для справки: это запрос агрегации в процессе выполнения, который я пытаюсь расширить:
db.getCollection('some_collection').aggregate([
{ $group: { '_id': '$commandName', 'docs': {$addToSet: '$$ROOT'} } },
{ $sort: {'_id.docs.???': 1}}
])
Пост-разрешенное редактирование
Спасибо за ответы. Я получил то, что мне было нужно. Для дальнейшего использования это полный запрос, который выполнит то, что было запрошено , а также вернет список отфильтрованных документов, а не групп .
db.getCollection('some_collection').aggregate([
{ $sort: {'executionDate': 1}},
{ $group: { '_id': '$commandName', 'result': { $last: '$$ROOT'} } },
{ $replaceRoot: {newRoot: '$result'} }
])
Результат запроса без Этап $replaceRoot
будет выглядеть следующим образом:
[
{
"_id": "migration_a",
"result": {
"commandName" : "migration_a",
"executionDate" : ISODate("2005-11-08T11:58:52.000Z")
}
},
{
"_id": "migration_b",
"result": {
"commandName" : "migration_b",
"executionDate" : ISODate("2016-06-02T19:48:34.000Z")
}
}
]
Внешние _id
и _result
- это просто "групповые обертки" вокруг фактического документа, который я хочу, который вложен в result
ключПеремещение вложенного документа в корень результата выполняется с использованием этапа $replaceRoot
. Результат запроса при использовании этого этапа:
[
{
"commandName" : "migration_a",
"executionDate" : ISODate("2005-11-08T11:58:52.000Z")
},
{
"commandName" : "migration_b",
"executionDate" : ISODate("2016-06-02T19:48:34.000Z")
}
]