MongoDB聚合查询问题:匹配非当前用户发送的未读消息
MongoDB聚合查询:检测非自身发送的未读消息问题解决
问题场景
现有用户集合数据结构(简化后):
[ { _id: ObjectId('641b5665894f755f6dc422a2'), directMsgs: { person1: [ { authorId: ObjectId('6454bb4e33b90133ba752e96'), isRead: false }, { authorId: ObjectId('641b5665894f755f6dc422a2'), isRead: true } ], person2: [ { authorId: ObjectId('641b5665894f755f6dc422a2'), isRead: true }, { authorId: ObjectId('642b5765834f755f6dc422b3'), isRead: true } ] } } ]
通过$objectToArray投影后,directMsgs转为键值对数组结构。需求是:查询指定_id的用户是否存在**非自身发送(authorId≠用户_id)且未读(isRead=false)**的消息。
原查询语句在使用$ne操作符时无法正确匹配,去掉该条件或改为$eq时正常。
问题原因
原查询的$match条件是针对整个文档的数组字段,只要directMsgs.v数组中存在任意一个元素满足authorId≠uid,同时存在任意一个元素满足isRead=false,就会匹配文档,但这两个条件可能对应不同的消息对象,不符合“同一个消息同时满足两个条件”的需求。
解决方案
需要先展开嵌套数组,再针对单个消息对象做条件匹配,最后判断是否存在符合条件的消息。以下是两种实现方式:
方式1:直接返回是否存在符合条件的消息
const userId = '641b5665891f755f6dd422a2' const uid = new ObjectId(userId) const hasUnreadMsg = await User.aggregate([ // 先匹配目标用户,减少后续处理数据量 { $match: { _id: uid } }, // 将directMsgs对象转为键值对数组 { $project: { directMsgs: { $objectToArray: '$directMsgs' } } }, // 展开对话列表 { $unwind: '$directMsgs' }, // 展开对话中的消息列表 { $unwind: '$directMsgs.v' }, // 匹配符合条件的消息:非自身发送且未读 { $match: { 'directMsgs.v.authorId': { $ne: uid }, 'directMsgs.v.isRead': false } }, // 标记存在符合条件的消息 { $group: { _id: null, exists: { $first: true } } } ]) // 结果判断:若数组长度大于0则存在未读消息 const exists = hasUnreadMsg.length > 0
方式2:返回匹配的消息详情(如果需要)
const userId = '641b5665891f755f6dd422a2' const uid = new ObjectId(userId) const matchedMsgs = await User.aggregate([ { $match: { _id: uid } }, { $project: { directMsgs: { $objectToArray: '$directMsgs' } } }, { $unwind: '$directMsgs' }, { $unwind: '$directMsgs.v' }, { $match: { 'directMsgs.v.authorId': { $ne: uid }, 'directMsgs.v.isRead': false } }, // 保留需要的字段 { $project: { conversationKey: '$directMsgs.k', authorId: '$directMsgs.v.authorId', isRead: '$directMsgs.v.isRead' } } ]) // matchedMsgs不为空则存在符合条件的消息
关键优化点
- 先执行
$match筛选目标用户,避免对全集合做后续操作,提升查询效率。 - 通过两次
$unwind展开嵌套数组,将每个消息对象单独处理,确保条件匹配的是同一个消息。
内容的提问来源于stack exchange,提问作者Joey Kyber
相关产品推荐
相关产品推荐

