【问题标题】:Grouping in mongoose aggregation according to condition根据条件在猫鼬聚合中分组
【发布时间】:2021-05-30 05:36:41
【问题描述】:

我正在构建一个基于 MERN 堆栈的聊天应用程序,需要获取特定用户的所有聊天记录。

这是我的聊天消息架构:

const message = mongoose.Schema({
  from: {
    type: Schema.Types.ObjectId,
    ref: "users",
    required: true,
  },
  to: {
    type: Schema.Types.ObjectId,
    ref: "users",
    required: true,
  },
  text: { type: String, required: false },
  imgLink: { type: String, required: false },
  sentAt: { type: Date, required: true },
  deliveredAt: { type: Date, required: false },
  readAt: { type: Date, required: false },
});

有没有办法获取用户的所有聊天记录并按发送/接收这些聊天记录的人分组。

我使用了这个聚合管道

const fetchChatPipeline = (_id) => {
  return [
    {
      $match: {
        $or: [
          {
            to: mongoose.Types.ObjectId(_id),
          },
          {
            from: mongoose.Types.ObjectId(_id),
          },
        ],
      },
    },
    {
      $sort: {
        sentAt: 1,
      },
    },
    {
      $group: {
        _id: "$from",
        from: { $first: "$from" },
        to: { $first: "$to" },
        messages: {
          $push: {
            text: "$text",
            imgLink: "$imgLink",
            sentAt: "$sentAt",
            deliveredAt: "$deliveredAt",
            readAt: "$readAt",
          },
        },
      },
    },
    {
      $lookup: {
        from: "users",
        localField: "from",
        foreignField: "_id",
        as: "from",
      },
    },
    {
      $unwind: {
        path: "$from",
        preserveNullAndEmptyArrays: false,
      },
    },
    {
      $lookup: {
        from: "users",
        localField: "to",
        foreignField: "_id",
        as: "to",
      },
    },
    {
      $unwind: {
        path: "$to",
        preserveNullAndEmptyArrays: false,
      },
    },
    {
      $project: {
        to: {
          _id: 1,
          name: 1,
        },
        from: {
          _id: 1,
          name: 1,
        },
        messages: 1,
      },
    },
  ];
};

得到如下结果:

{
    "chats": [
        {
            "_id": "60368ee8a4e8494c74ccbeec",
            "from": {
                "_id": "60368ee8a4e8494c74ccbeec",
                "name": "Jaivardhan Singh"
            },
            "to": {
                "_id": "603a637ab356a309dcca9099",
                "name": "Jai Singh "
            },
            "messages": [
                {
                    "text": "hello",
                    "sentAt": "2021-02-27T16:33:40.335Z"
                },
                {
                    "text": "What you upto",
                    "sentAt": "2021-02-27T16:34:16.852Z"
                }
            ]
        },
        {
            "_id": "603a637ab356a309dcca9099",
            "from": {
                "_id": "603a637ab356a309dcca9099",
                "name": "Jai Singh "
            },
            "to": {
                "_id": "60368ee8a4e8494c74ccbeec",
                "name": "Jaivardhan Singh"
            },
            "messages": [
                {
                    "text": "Hi",
                    "sentAt": "2021-02-27T16:35:32.343Z"
                },
                {
                    "text": "Nothing just chilling",
                    "sentAt": "2021-02-27T16:35:41.720Z"
                },
                {
                    "text": "What you upto",
                    "sentAt": "2021-02-27T16:35:49.662Z"
                }
            ]
        }
    ]
}

有没有办法可以将这两个聊天合并到结果中,因为它们有共同的参与者。谢谢。

【问题讨论】:

  • 只需$group by null,因为您已经在$match 阶段过滤了用户:像这样:docs.mongodb.com/manual/reference/operator/aggregation/group/…
  • 但这样做会将所有消息合并在一起,即使聊天中的参与者不同。在上面的示例中,只有 2 人之间的聊天,但如果我们添加第三人,他的聊天也会合并
  • 但是$matchstage 会过滤所有第三人称。 $match 将只包括发送者(来自)和接收者(到)对吧?
  • 如您所见,匹配过滤器中有一个 $or,因此它返回所有由 _id 发送或由 _id 接收的聊天。因此,如果具有 _id 的用户与第三人聊天,他的结果也将包含在分组中
  • 好的。如果有帮助,请检查更新的答案。

标签: node.js mongodb mongoose aggregation


【解决方案1】:

只需将您的$match 阶段更改为如下并将$group 更改为null

{
    $match: {
        $or: [
            { to: mongoose.Types.ObjectId(_id) },
            { from: mongoose.Types.ObjectId(_id) }
        ],
        to: { $ne: mongoose.Types.ObjectId(_id) }
    }
}

【讨论】:

    猜你喜欢
    • 2015-03-04
    • 2018-08-22
    • 1970-01-01
    • 2017-03-30
    • 2015-05-02
    • 1970-01-01
    • 2015-05-19
    • 1970-01-01
    • 2021-04-14
    相关资源
    最近更新 更多