#database #mongodb #mongoose #nosql #conditional-statements
#База данных #mongodb #мангуст #nosql #условные операторы
Вопрос:
Я пытаюсь запросить свою коллекцию совпадений (игр) и выяснить, отправил ли определенный пользователь уже данные в массив объектов reportMessages.
const results = await Match.findOne({ 'users': req.params.userIdOfReportSender, '_id': req.params.matchId, 'reportMessages.sentBy': req.params.userIdOfReportSender }, 'reportMessages' )
Однако приведенный выше запрос возвращает следующее:
{
_id: 5fd382c65d5395e0778f2f8a,
reportMessages: [
{
_id: 5fd610f27ae587189c45b6ca,
content: 'jajatest',
timeStamp: 2020-12-13T13:02:42.102Z,
sentBy: 'XbVvm6g3nsRmPg3P1pBvVl84h6C2'
},
{ sentBy: "'anotheruser123" }
]
}
Как я могу заставить его возвращать только первое сообщение reportMessage, то есть отправленное XbVvm6g3nsRmPg3P1pBvVl84h6C2?
Документы Mongoose findOne (https://mongoosejs.com/docs/api.html#model_Model.findOne ) покажите, что вы можете указать аргументы, указывающие, какие поля следует выбрать (в их случае «длина имени»), но не показывайте способ выбора полей только в том случае, если они соответствуют определенному условию.
Возможно ли это вообще? Пытался погуглить этот, казалось бы, простой вопрос в течение довольно долгого времени, но безуспешно
С уважением
Ответ №1:
С помощью этого запроса агрегации вы можете получить только тот вложенный документ, который вам нужен:
Match.aggregate([
{
$match: { _id: req.params.matchId }
},
{
$project: {
reportMessages: {
$filter: {
input: '$reportMessages',
as: 'msg',
cond: { $eq: ['$msg.sentBy', req.params.userIdOfReportSender] }
}
}
}
},
{
$project: {
reportMessage: { $arrayElemAt: [ '$reportMessages', 0 ] },
}
},
{ $replaceWith: '$reportMessage' }
]);
Обратите внимание, что вам нужно указать документ только _id
для получения одного результата, поскольку _id
s уникальны.
Комментарии:
1. Спасибо. После обертывания ObjectId вокруг req.params.MatchID в условии $match это сработало. Все еще не уверен, почему это должно быть сделано для этого запроса агрегации, но, например, в операции ‘updateOne’ мне не нужно оборачивать вокруг него ObjectId и я могу продолжать использовать значение req.params.MatchID (которое, я полагаю, является строкой).