【发布时间】:2022-01-20 01:32:20
【问题描述】:
我有 2 个收藏。
Collection Name: chats
Chat {
_id : Object(Id)
mssg : string
room : Object Ref (room _id)
creationDate: DateTimeStamp
}
Collection Name: rooms
Room {
_id : Object(Id)
chatMssgs: [Object Ref (Chat_id_1), Object Ref (Chat_id_2), Object Ref (Chat_id_x)]
roomName: string
creationDate: DateTimeStamp
}
我正在尝试使用猫鼬聚合管道按最新聊天消息的顺序对房间进行排序。为此,我正在执行以下操作:
- 按最新聊天消息排序(使用创建日期)
- 使用 Lookup 获取聊天 mssg 的引用房间
- 展开生成的房间数组
- 使用 replaceRoot 将房间数组结果作为数组中的主要对象。
- 返回唯一的房间列表,而不会丢失最新聊天消息日期的排序。
到目前为止,以下代码可以运行到第 4 点。
await Chat.aggregate([
{$sort: {creationDate: -1}},
{$lookup: {
from: "rooms",
localField: "room",
foreignField: "_id",
as: "chat_room"
}
},
{$unwind: "$chat_room"},
{$replaceRoot: {newRoot: "$chat_room"}},
])
这就是我迷路的地方。如果我保持当前聚合代码不变,它可以工作,但我的房间 ID 有重复。这是因为一个房间可以有多个聊天消息。如果我在 replaceRoot 之后使用 $group,我的排序就会消失,并且最新聊天消息的顺序也会丢失。
理想情况下,我会尝试按最后的聊天消息对房间进行排序。我使用聚合,因为我还需要使用 addField 对房间后记执行一些计数,并且我为此查询使用分页,因此需要偏移和限制以保持查询相对较快。
按降序返回包含最新聊天消息的房间的最佳方式是什么? 所以房间 1 将有最新的 mssg,房间 2,... 等等,直到房间 x 显示最早发布的 mssg。
更新:在第一次回复中尝试了建议的解决方案后,我得到:
[
{
"_id": 3,
"creationDate": ISODate("2014-01-03T08:00:00Z"),
"mssg": "ghi",
"room": 2
},
{
"_id": 2,
"creationDate": ISODate("2014-01-02T08:00:00Z"),
"mssg": "def",
"room": 1
}
]
这也是我在使用方法时遇到的问题。如何让输出看起来像这样?
[
{
"_id": 2,
"roomName": "room 2"
"creationDate": ISODate("2014-01-01T08:00:00Z"),
"chatMssgs": [3 ],
},
{
"_id": 1,
"roomName": "room 1"
"creationDate": ISODate("2014-01-01T08:00:00Z"),
"chatMssgs": [1,2 ],
}
]
【问题讨论】: