0

I'm trying to get all of the messages between User A and any other user.

My schema is:

const MostRecentMessageSchema = new Schema({
  to: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "user"
  },
  from: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "user"
  },
  conversation: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "conversation"
  },
  date: {
    type: Date,
    default: Date.now
  }
});

And my query:

    await MostRecentMessages.aggregate(
      [
        {
          $match: {
            $or: [
              {
                to: id
              },
              {
                from: id
              }
            ]
          }
        },
        { $sort: { date: -1 } },
        {
          $group: {
            _id: "$from",
            from: {
              $first: "$from"
            },
            to: {
              $first: "$to"
            },
            conversation: {
              $first: "$conversation"
            },
            date: {
              $first: "$date"
            }
          }
        },
        {
          $lookup: {
            from: "conversations",
            localField: "conversation",
            foreignField: "_id",
            as: "conversation"
          }
        },
        { $unwind: { path: "$conversation" } },
        {
          $project: {
            from: {
              $cond: { if: { $eq: ["$to", id] }, then: "$from", else: "$to" }
            },
            to: {
              $cond: { if: { $eq: ["$to", id] }, then: "$to", else: "$from" }
            },
            conversation: "$conversation"
          }
        }
      ],
      function(err, docs) {
        if (err) console.log(err);
        else console.log("docs", docs);

        return res.json(docs);
      }
    );

However, this keeps returning an empty array. What am I doing wrong here? I also need to populate the conversation field, which is why I am doing the $lookup, but something else is fundamentally wrong, because it's not finding any documents.

Mike K
  • 7,621
  • 14
  • 60
  • 120

1 Answers1

0

Figured it out. For anyone coming here with the same problem, see this answer. The id string must be converted to an ObjectID


How I solved it:

    await MostRecentMessages.aggregate(
      [
        {
          $match: {
            $or: [
              { from: mongoose.Types.ObjectId(id) },
              { to: mongoose.Types.ObjectId(id) }
            ]
          }
        },
        { $project: { _id: 1, from: 1, to: 1, conversation: 1, date: 1 } },
        { $sort: { date: -1 } },
        {
          $group: {
            _id: "$sender",
            from: { $first: "$from" },
            to: { $first: "$to" },
            date: { $first: "$date" },
            conversation: { $first: "$conversation" }
          }
        }
      ],
      function(err, docs) {
        if (err) console.log(err);
        else console.log("docs", docs);

        return res.json(docs);
      }
    );
Mike K
  • 7,621
  • 14
  • 60
  • 120