#mongodb #mongodb-query
Вопрос:
Учитывая существующую коллекцию базы данных mongo с именем пользователи с некоторыми документами в ней, которая выглядит следующим образом :
{
"_id" : ObjectId("611a11a09500700009d09a12"),
"userId" : "abc",
"createdAt" : ISODate("2021-08-14T07:22:00.535Z"),
"isActive" : true,
"isEligible" : true
},
{
"_id" : ObjectId("611a11a09500700009d09a13"),
"userId" : "abc",
"createdAt" : ISODate("2021-08-15T07:20:00.535Z"),
"isActive" : true,
"isEligible" : true
},
{
"_id" : ObjectId("611a11a09500700009d09a14"),
"userId" : "def",
"createdAt" : ISODate("2021-08-15T07:22:00.535Z"),
"isActive" : true,
"isEligible" : true
},
{
"_id" : ObjectId("611a11a09500700009d09a15"),
"userId" : "abc",
"createdAt" : ISODate("2021-08-16T07:18:00.535Z"),
"isActive" : true,
"isEligible" : true
},
{
"_id" : ObjectId("611a11a09500700009d09a16"),
"userId" : "abc",
"createdAt" : ISODate("2021-08-16T07:20:00.535Z"),
"isActive" : true,
"isEligible" : true
}
{
"_id" : ObjectId("611a11a09500700009d09a17"),
"userId" : "def",
"createdAt" : ISODate("2021-08-16T07:22:00.535Z"),
"isActive" : true,
"isEligible" : true
}
Помимо ключей, упомянутых в каждом из вышеприведенных документов, может быть также несколько других ключей.
Здесь я хочу написать запрос, который выполняет следующие операции и возвращает данные:
- Выберите записи с createdAt больше или равно «2021-08-15T00:00:00.000 Z».
- Для каждого идентификатора пользователя возвращайте только последнюю запись, т. е. запись, отсортированную по createdAt в порядке убывания.
- Возвращаемый документ должен содержать все ключи, которые присутствуют в исходном документе. Количество ключей может быть намного больше, чем указано в документе. Таким образом, запрос должен автоматически возвращать все ключи.
Ниже приведен пример вывода, который требуется:
{
"_id" : ObjectId("611a11a09500700009d09a16"),
"userId" : "abc",
"createdAt" : ISODate("2021-08-16T07:20:00.535Z"),
"isActive" : true,
"isEligible" : true
}
{
"_id" : ObjectId("611a11a09500700009d09a17"),
"userId" : "def",
"createdAt" : ISODate("2021-08-16T07:22:00.535Z"),
"isActive" : true,
"isEligible" : true
}
Ответ №1:
Вы можете использовать этот этап агрегирования:
- Сначала
$match
нужно получить только те документы, дата которых больше или равна желаемой дате. - Затем
$sort
установить значения первой позиции в порядке убывания. - И последнее
$group
,userId
получив только первое значение (в соответствии с порядком-1
, первое значение будет в соответствии сdesc
порядком)
db.collection.aggregate([
{
"$match": {
"createdAt": {
"$gte": ISODate("2021-08-15T00:00:00.000Z")
}
}
},
{
"$sort": {
"createdAt": -1
}
},
{
"$group": {
"_id": "$userId",
"createdAt": {
"$first": "$createdAt"
}
}
}
])
Пример здесь
Кроме того, если ObjectId
для вас важен конечный результат, вы также можете добавить один такой этап.
Комментарии:
1. Спасибо за ответ. Просто обновление, в вашем ответе нам нужно упомянуть все ключи, которые нам нужно вернуть в операторе «$project» вручную. Но я хочу, чтобы запрос автоматически возвращал все ключи, так как количество ключей может быть большим. Я также обновил вопрос более четкими инструкциями и был бы признателен, если бы вы могли предоставить обновленную информацию о решении для того же самого.
2. Ты имеешь в виду что-то вроде этого . Обратите внимание, что я добавил новое значение
newValue
, которое отображается, если оно существует, в противном случае будет равно нулю. Но вы должны вручную добавить все параметры в$project
или альтернативно задать значения вdata
поле, подобное этому .3. С тех пор как нет. количество ключей может быть большим, было бы сложно добавить все параметры в $project вручную, я бы хотел, чтобы запрос группировал данные по идентификатору пользователя и выбирал последнюю запись для каждого идентификатора пользователя и возвращал все ключи для последней записи, как показано в примере ответа.
4. Затем вы можете использовать этот запрос с помощью
$replaceRoot
. Если это сработает для вас, я могу отредактировать свой ответ.5. Упомянутый вами запрос, в котором используется $replaceRoot, возвращает результат в том же формате, что и желаемый. Но он не поддерживает порядок сортировки в createdAt. Когда я запускал запрос несколько раз, записи не сортировались в порядке убывания createdAt. Вы можете увидеть то же самое на mongoplayground.net/p/Q4A0UJ_E4u2