在 Mongodb 上,我有一个保存聊天数据的“conversations2”集合和一个被系统阻止的“user_blocked”集合。在根据 userId 拉取聊天记录时,我需要拉取 user_blocked 中与 otherUserId 不匹配的 ID。我下面的查询有效,但对于具有大量消息的用户来说太慢了(例如,对于具有 32 个 ID 的用户来说,有 45 万条记录)。我是否有机会加快速度或通过不同的路线接收此查询? (我的目标是获取用户的未读消息数,不包括任何阻止)预先感谢您的帮助。顺便添加conversations2中的userId_1和otherUserId_1索引。 user_blocked 中添加了 id_1 索引。
db.conversations2.aggregate([
{
$match: {
userId: 32
}
},
{
$lookup: {
from: "user_blocked",
localField: "otherUserId",
foreignField: "id",
as: "blockedUsers"
}
},
{
$match: {
blockedUsers: {
$eq: []
}
}
},
{
$group: {
_id: "$userId",
unreadMessageCount: {
$sum: "$unreadMessageCount"
}
}
}
])
conversations2 集合示例数据;
{
"_id": {
"$oid": "65c0f64030054c4b8f0481a0"
},
"otherUserId": {
"$numberLong": "45"
},
"userId": {
"$numberLong": "32"
},
"lastMessage": "test",
"lastMessageTime": {
"$date": "2024-02-21T10:36:44.592Z"
},
"lastMessageType": 1,
"lastMessageWay": "in",
"unreadMessageCount": 29
}
user_blocked 示例数据;
{
"_id": {
"$oid": "66033f989bba279fe7d0862a"
},
"id": {
"$numberLong": "45"
}
}
1. 由于您在此查询中仅获得
unreadMessageCount
,因此第一个小优化是将其添加到第一个 $match
阶段。因为当 0
时,无论用户是否被阻止,总数都不会改变。所以只检查 unread > 0
。
{
$match: {
userId: 32,
unreadMessageCount: { $gt: 0 }
}
}
2. 下一个优化将需要更改数据/结构:
添加一个类似
otherUserBlocked: true/false
的字段并为其建立索引。最初将其默认为 false
(没有用户被阻止),然后使用与您已有的管道类似的管道将其设置为 true
。
如果您跳过初始默认值,则需要将子句
{ otherUserBlocked: { $exists: true } }
添加到下面的查询中。
每次用户被阻止时,您就已经将其添加到
user_blocked
集合中。添加另一个步骤以同时使用 conversations2
更新 { $match: { otherUserId: blocked_user_id } }
并设置 otherUserBlocked: true
。比如:
db.conversations2.updateMany({
otherUserId: 46
},
{
$set: {
otherUserBlocked: true
}
})
如果他们被解锁,请设置它
false
。
然后,您的聚合管道可以在第一个 $match
阶段使用它,并完全消除对
$lookup
以及第二个
$match
阶段的需要。管道变成:
db.conversations2.aggregate([
{
$match: {
userId: 32,
otherUserBlocked: false,
unreadMessageCount: { $gt: 0 }
}
},
{
$group: {
_id: "$userId",
unreadMessageCount: { $sum: "$unreadMessageCount" }
}
}
])
当您想要实际显示未读消息而不仅仅是计数时,这两项更改也很有用。