【问题标题】:Mongodb Aggregate - Get sent and received messageMongodb Aggregate - 获取发送和接收的消息
【发布时间】:2021-04-21 07:45:47
【问题描述】:

我正在为我的应用构建一个简单的聊天功能。我在发送和接收消息时遇到了一点问题。

这是我的消息架构:

const MessageSchema = new mongoose.Schema({
    from: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User',
        required: true
    },
    to: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User',
        required: true
    },
    text: {
        type: String,
        required: true
    },
    seen: {
        type: Boolean,
        default: false
    },
    createdAt: {
        type: Date,
        required: true
    }
});

假设我有这个消息文件:

[
  {
    from: "5fef2536ad845e385c34a22f",  // My Own ID
    to: "5fef2575ad845e385c34a232"   // Example user "John",
    text: "I sent this"
    ...
  }, 
  {
    from: "5fffdc903eaf522cb8d20994",  // Example user "Dave"
    to: "5fef2536ad845e385c34a22f"   // My Own ID,
    text: "Dave sent this"
    ...
  }
]

这是我对发送和接收消息的看法

await Message.aggregate([
  {
    $match: {
      $or: [ { from: req.user._id },{ to: req.user._id }]
    }
  },
  { $sort: { createdAt: -1 } },
  {
    $group: {
      _id: '$to',
      from: { $first: '$from' },
      text: { $first: '$text' } 
     ...
    }
  },
  {
    $project: { 
      _id: 0,
      to: '$_id',
      from: 1,
      text: 1
    } 
  }
])

上述聚合产生:

[ 
  // This is the message I sent
  {
    from: "5fef2536ad845e385c34a22f",
    to: "5fef2575ad845e385c34a232",
    text: "I sent this"
    ...
  }
  
  ...
  // I CAN'T FETCH RECEIVED MESSAGES
]

我能够得到最后一个我发送的消息,因为我只将它们与to 分组在一起,我只发送了哪些消息。我想不出一种方法如何通过分别分组来同时获取已发送和已接收的消息。

我应该改变我为我的消息建模的方式吗?如果您能帮助我,我将不胜感激。

【问题讨论】:

    标签: mongodb mongoose aggregation-framework


    【解决方案1】:

    您正在查找的部分是 $facet,它有助于对传入数据进行分类。您可以并行运行多个聚合,如下所示。下面的代码可能是一个示例,向您展示如何使用$facet

    在这里,我创建了两个数组,它们是 sentreceived。您可以运行单独的单独聚合阶段来获取所需的数据

    {
        $facet: {
          sent: [
            { $match: { from: "5fef2536ad845e385c34a22f" }},
            { $sort: { createdAt: -1 } },
            { $limit: 1 }
          ],
          received: [
            { $match: { to: "5fef2536ad845e385c34a22f" }},
            { $sort: { createdAt: -1 } },
            { $limit: 1 }
          ]
        }
    }
    

    工作mongo playground

    【讨论】:

    • 嗨@varman!为什么我每个 sentreceived 得到 2 个文档,而我希望它们每个只有 1 个?
    • 您如何分别识别您发送的内容和收到的内容?
    • 很抱歉,我没有完全理解您的意思。
    • 您可以使用$concatArray。试试自己,如果你失败了,请告诉我
    • 太棒了!我像这样使用它并且效果很好。 $project: { result: { $concatArrays: ['$sent', '$received'] } }
    猜你喜欢
    • 1970-01-01
    • 2018-07-14
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-19
    • 2016-04-08
    相关资源
    最近更新 更多