通过 mongodb 中的查找从管道中删除被阻止的用户

问题描述 投票:0回答:1

在 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"
  }
}
mongodb mongodb-query nosql aggregation-framework nosql-aggregation
1个回答
0
投票

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" } } } ])

Mongo Playground 与新字段

当您想要实际显示未读消息而不仅仅是计数时,这两项更改也很有用。

© www.soinside.com 2019 - 2024. All rights reserved.