You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用MongoDB聚合查询找出与指定用户有共同点赞动态的用户及最多重合者

问题描述

现有likes集合,数据结构如下:

// 1
{
    "_id": ObjectId("1"), 
    "masterid": ObjectId("45678"), // 动态发布者的用户ID
    "momentid": ObjectId("123456"),// 动态ID
    "userid": ObjectId("123456"), // 点赞者的用户ID
    "avatar": "1660531471959.jpg", // 点赞者头像
    "username": "userA", // 点赞者用户名
    "timestamp": NumberInt("1677072930") // 点赞时间戳
}

// 2
{
    "_id": ObjectId("63f61d8d99b4ee0004e76e03"),
    "masterid": ObjectId("45678"),
    "momentid": ObjectId("123456"),
    "userid": ObjectId("45678"),
    "avatar": "defaultAvatar.jpg",
    "username": "userB",
    "timestamp": NumberInt("1677073805")
}

需求:找出与用户A(userid为ObjectId("123456"))点赞过相同动态的其他用户,统计双方共同点赞的动态数量,最终确定共同点赞数量最多的用户。例如用户A点赞动态S、X,用户B点赞S,用户C点赞S、X、Y,需统计出B与A有1个共同动态,C与A有2个共同动态,C是共同数量最多的用户。

用户尝试了以下聚合查询但未成功:

db.likes.aggregate([

  { $match: { userid: ObjectId("id") } },

  {
    $group: {
      _id: "$momentid",
      count: { $sum: 1 },
      users: { $addToSet: "$userid" }
    }
  },
  
  {
    $lookup: {
      from: "likes",
      let: { users: "$users", momentid: "$_id" },
      pipeline: [
        { $match: { $expr: { $and: [
          { $eq: [ "$momentid", "$$momentid" ] },
          { $ne: [ "$userid", ObjectId("id") ] },
          { $in: [ "$userid", "$$users" ] }
        ] } } },
        { $project: { _id: 0, userid: 1 } }
      ],
      as: "otherLikes"
    }
  },
 
  {
    $project: {
      _id: "$moment.userid",
      count: { $size: "$otherLikes.userid" },
      users: "$otherLikes.userid"
    }
  },
  
  { $sort: { count: -1 } }
])
问题分析与解决方案

原查询的问题在于:

  1. $group阶段的users字段仅收集了用户A的ID,后续$lookup中的$in条件无实际意义;
  2. $project阶段引用了不存在的$moment.userid字段,导致结果异常;
  3. 整体逻辑未正确关联用户A的点赞动态与其他用户的点赞记录,无法统计共同数量。

正确的聚合管道如下:

// 替换为用户A的实际ObjectId
const userAId = ObjectId("123456");

db.likes.aggregate([
  // 1. 获取用户A点赞过的所有动态ID
  { $match: { userid: userAId } },
  { $group: { _id: null, userAMoments: { $addToSet: "$momentid" } } },
  
  // 2. 关联likes集合,统计其他用户的共同点赞数量
  {
    $lookup: {
      from: "likes",
      let: { targetMoments: "$userAMoments" },
      pipeline: [
        { $match: { 
          $expr: { 
            $and: [
              { $in: [ "$momentid", "$$targetMoments" ] },
              { $ne: [ "$userid", userAId ] }
            ]
          }
        } },
        { $group: { 
          _id: "$userid",
          commonCount: { $sum: 1 },
          username: { $first: "$username" },
          avatar: { $first: "$avatar" }
        } }
      ],
      as: "commonUsers"
    }
  },
  
  // 3. 整理结果并按共同数量降序排序
  { $unwind: "$commonUsers" },
  { $replaceRoot: { newRoot: "$commonUsers" } },
  { $sort: { commonCount: -1 } }
])

步骤说明

  1. 收集用户A的点赞动态:通过$match筛选用户A的点赞记录,用$group将所有点赞过的动态ID存入数组;
  2. 统计其他用户的共同动态数:利用$lookup子管道,筛选出点赞过这些动态的非用户A记录,再按用户分组统计数量,同时保留用户名、头像信息;
  3. 整理排序结果:展开数组并将子文档转为根文档,最后按共同数量降序排列,数量最多的用户排在最前。

内容的提问来源于stack exchange,提问作者lionjoy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 00:21:26