Mongoose FindOne — возвращать только те поля, которые соответствуют условию

Я пытаюсь запросить свою коллекцию матчей (игр) и выяснить, отправлял ли определенный пользователь данные в массив объектов 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) показывают, что вы можете предоставить аргументы, чтобы указать, какие поля выбрать (в их случае «длина имени», но не показывать способ выбирать поля только в том случае, если они соответствуют определенному условию.

Это вообще возможно? Пытался гуглить этот, казалось бы, простой вопрос в течение довольно долгого времени, но безуспешно.

С уважением

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
0
0
290
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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, чтобы получить один результат, поскольку _ids уникальны.

Спасибо. После обертывания ObjectId вокруг req.params.matchId в условии $match это сработало. Все еще не уверен, почему это нужно делать для этого запроса агрегации, но, например. в операции updateOne мне не нужно оборачивать ObjectId вокруг него, и я могу продолжать использовать значение req.params.matchId (которое, как мне кажется, является строкой).

beyondtdr 14.12.2020 15:50

Другие вопросы по теме