聚合查询无法与用户A来回发送最新消息

我有一个MostRecentMessage模型,定义为

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

每当用户A向用户B发送消息时,都会创建一个文档(如果该文档不存在)。每次用户A向用户B发送消息时,都会使用新的conversationdate更新此文档。文件的示例是

_id: ObjectId(5dc46521cf670a0017d2434d)
to: ObjectId(5dc464ce2fd75700178c1ad4) // User B
from: ObjectId(5dc464fc2fd75700178c1ad5) // User A
conversation: ObjectId(5dc465c6cf670a0017d24363)
date: 2019-11-07T18:40:33.242+00:00
__v: 0

想法是,这将有助于跟踪所有最近发给特定用户的消息。

同样,用户B可以向用户A发送消息。与上面类似,将创建一个新文档,

_id: ObjectId(5dc46521cf670a0017d2434d)
to: ObjectId(5dc464fc2fd75700178c1ad5) // User A
from: ObjectId(5dc464ce2fd75700178c1ad4) // User B
conversation: ObjectId(5dc465c6cf670a0017d24363)
date: 2019-11-07T18:40:33.242+00:00
__v: 0

此文档将随着用户B发送给用户A的每条新消息而更新。

现在,下面是我的聚合查询..但问题是它只返回一个对话。可能有10个用户与用户A交谈,但仍只返回一个文档。

  const { id } = req.user;

  try {
    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: null,from: { $first: "$from" },to: { $first: "$to" },date: { $first: "$date" },conversation: { $first: "$conversation" }
          }
        },{
          $lookup: {
            from: "conversations",localField: "conversation",foreignField: "_id",as: "conversation"
          }
        },{ $unwind: { path: "$conversation" } },{
          $lookup: {
            from: "users",localField: "to",as: "to"
          }
        },{ $unwind: { path: "$to" } },localField: "from",as: "from"
          }
        },{ $unwind: { path: "$from" } }
      ],function(err,docs) {
        if (err) {
          console.log(err);
        } else {
          return res.json(docs);
        }
      }
    );
  } catch (err) {
    console.log(err);

    return res.status(500).send("Server error");
  }

我在这里做什么错了?


编辑:我现在所拥有的:

使用此代码,如果

User A messages User B,'Test1'
User B messages User A,'Test2'
User A messages User B,'Test3'

然后,两个用户都只会显示Test2消息。如何让“ Test3”同时显示给两个用户?

    await MostRecentMessages.aggregate(
      [
        {
          $match: {
            $or: [
              { from: mongoose.Types.ObjectId(id) },{ to: mongoose.Types.ObjectId(id) }
            ]
            // deletedBy: { $ne: id }
          }
        },{
          $group: {
            _id: {
              userConcerned: {
                $cond: {
                  if: {
                    $eq: ["$to",mongoose.Types.ObjectId(id)]
                  },then: "$to",else: "$from"
                }
              },interlocutor: {
                $cond: {
                  if: {
                    $eq: ["$to",then: "$from",else: "$to"
                }
              }
            },docs) {
        if (err) {
          console.log(err);
        } else {
          return res.json(docs);
        }
      }
xuchong891101 回答:聚合查询无法与用户A来回发送最新消息

正如我在评论中所说,小组赛是您获得独特结果的原因。诀窍是要创建2个字段,从'from'或'to'字段(取决于您在param中提供的objectId),代表您提供的用户及其对话者。 (无论“从”到“到”) 这是个主意,但我目前无法测试解决方案。

...

  {
    $group: {
      _id: {
      userConcerned: {
        $cond: {
          if: {
            $eq: [
              "$to",mongoose.Types.ObjectId(id)
            ]
          },then: "$to",else: "$from"
        }
      },interlocutor: {
        $cond: {
          if: {
            $eq: [
              "$to",then: "$from",else: "$to"
        }
      }
    },from: { $first: "$from" },to: { $first: "$to" },date: { $first: "$date" },conversation: { $first: "$conversation" }
    }
  }
  ...

Here's the POC

(如果您对'from'和'to'并不是很重要,则可以使用两个新创建的字段进行查找,并从分组阶段的from和to删除。

希望有帮助

---编辑--- 为了完成并解释我的答案: 使用此计算出的_id而不是null进行分组,将分组A和B之间的所有对话(A-> B或B-> A),A和C,A和D...。A始终位于“ userConcerned”中,其他对话者。 这样,您将获得A每次对话的文档,以及A和他的对话者之间的最新消息(由于先前的$ sort阶段和$ first累加器),而不必担心A是发送者还是接收者(从或到)。

本文链接:https://www.f2er.com/3141986.html

大家都在问