【问题标题】:Mongoose query to pull the latest document per conversationMongoose 查询以提取每个对话的最新文档
【发布时间】:2019-10-08 06:21:37
【问题描述】:

我正在尝试显示其他用户发送给用户的最新消息。

如果,

User A sends Message 1 to User B,
User A sends Message 2 to User B,
User B sends Message 3 to User A,
User A sends Message 4 to User B,
User C sends Message 5 to User B

如果我是用户 B,查看我的收件箱,只返回用户 A 的消息 4 给用户 B 和用户 C 的消息 5 给用户 B。

我该怎么做?到目前为止我已经尝试过了:

    const messages = await Conversation.find({ recipient: id })
      .sort({ date: -1 })
      .distinct("sender")
      .populate("sender")

但是 a) 它没有填充 sender,它返回 messages [ 5d9b5142d6606f12f5434d41 ] 并且 b) 我不确定这是正确的查询。

我的模特:

const conversationSchema = new Schema({
  sender: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "user"
  },
  senderHandle: {
    type: String,
    required: true
  },
  recipient: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "user"
  },
  text: {
    type: String,
    required: true
  },
  unread: {
    type: Boolean,
    default: true
  },
  date: {
    type: Date,
    default: Date.now
  }
});

编辑:

我试过这个:

    await Conversation.aggregate(
      [
        // Matching pipeline, similar to find
        {
          $match: {
            recipient: id
          }
        },
        // Sorting pipeline
        {
          $sort: {
            date: -1
          }
        },
        // Grouping pipeline
        {
          $group: {
            _id: "$sender",
            text: {
              $first: "$text"
            },
            date: {
              $first: "$date"
            }
          }
        },
        // Project pipeline, similar to select
        {
          $project: {
            _id: 0,
            sender: "$_id"
            text: 1
          }
        }
      ],
      function(err, messages) {
        // Result is an array of documents
        if (err) {
          return res.status(400).send({
            message: getErrorMessage(err)
          });
        } else {
          console.log("latestMessages", messages);
          return res.json(messages);
        }
      }
    )

来自here 的回答,但它返回一个空数组 + 它似乎不会填充sender

【问题讨论】:

    标签: javascript node.js mongodb mongoose


    【解决方案1】:

    更改匹配管道

        $match: {
              recipient: mongoose.Types.ObjectId(id);
        }
    

    在管道末尾添加这些

    {
        $lookup: {
           from: "users",
           localField: "sender",
           foreignField: "_id",
           as: "sender"
        }
     }
    
    { "$unwind": { path: "$sender" } }
    

    【讨论】:

    【解决方案2】:

    Distinct 返回一个 id 数组而不是对象数组,因此,它没有属性,您无法填充它。

    由于您想获取最新消息,我建议您使用 findOne 而不是 find。

    const message = await Conversation.findOne({recipient: id}, {}, { 
                    sort: { 'date' : -1 } })
                    .populate('sender');
    

    【讨论】:

    • 这样只会给用户B返回最新的消息,如果有用户C,用户D怎么办?我想要所有用户的所有最新消息给用户 B
    • 在这种情况下,您应该使用“查找”和发件人:$ne(userB._id)。这不会只给你来自每个用户的最后一条消息,而是会给你所有发给用户 B 的消息。我认为在你已经得到数组之后它可能需要更多的处理。
    • 可能作为后备,但我正在寻找可以执行此操作的单个查询,这样我就不必浪费不必要的计算能力,尤其是在我有数千条消息的情况下跨度>
    猜你喜欢
    • 1970-01-01
    • 2020-12-04
    • 2018-04-06
    • 2017-02-28
    • 2021-11-15
    • 1970-01-01
    • 2012-05-10
    • 2015-04-27
    • 1970-01-01
    相关资源
    最近更新 更多