首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MongoDB聚合$graphLookup -在以下关系集合中查找共同的“连接”

MongoDB聚合$graphLookup -在以下关系集合中查找共同的“连接”
EN

Stack Overflow用户
提问于 2018-12-01 15:22:36
回答 1查看 1.7K关注 0票数 1

我收集了“谁在跟踪谁”(如Instagram):

代码语言:javascript
复制
db.users.insertMany([
  { _id: 1, name: "Arnold Schwarzenegger" },
  { _id: 2, name: "James Earl Jones" },
  { _id: 3, name: "Harrison Ford" },
  { _id: 4, name: "Jennifer Lawrence" }
]);

db.follows.insertMany([
  { _id: 12, follower: 1, following: 2 },
  { _id: 13, follower: 1, following: 3 },
  { _id: 24, follower: 2, following: 4 },
  { _id: 23, follower: 2, following: 3 }
]);

我试图向其他用户推荐他们可以跟踪的其他用户。例如,他们可以跟踪哪些其他人;建议的追随者,根据现有的共同联系的数量排序。

在本例中:

代码语言:javascript
复制
+--------+--------------+----------+
|   A    | is following |    B     |
+--------+--------------+----------+
| Arnold | ->           | James    |
| Arnold | ->           | Harrison |
| James  | ->           | Jennifer |
| James  | ->           | Harrison |
+--------+--------------+----------+

阿诺德和詹姆斯之间的,谁能跟随阿诺德?(不包括现有的连接)

代码语言:javascript
复制
The answer should be: Jennifer

这是一次失败的尝试:

代码语言:javascript
复制
db.users.aggregate([
  {
    $match: { _id: 1 } // Arnold
  },
  {
    $graphLookup: {
      from: "follows",
      startWith: "$_id",
      connectFromField: "following",
      connectToField: "follower",
      maxDepth: 1,
      as: "connections",
    }
  }
]);

其结果是:

代码语言:javascript
复制
  {
    "_id": 1,
    "name": "Arnold Schwarzenegger",
    "connections": [
      {
        "_id": 24,
        "follower": 2,
        "following": 4
      },
      {
        "_id": 13,
        "follower": 1,
        "following": 3
      },
      {
        "_id": 23,
        "follower": 2,
        "following": 3
      },
      {
        "_id": 12,
        "follower": 1,
        "following": 2
      }
    ]
  }

我想我需要做一些放松,但我现在有点卡住了

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-12-02 11:56:19

以下是两种可能的方法。(我还没有用更大的数据集进行测试,所以您的里程可能会有所不同!)

第一个构建在您的$graphLookup阶段上:

代码语言:javascript
复制
db.users.aggregate([
  { $match: { _id: 1 }},
  { $graphLookup: {
    from: 'follows',
    startWith: '$_id',
    connectFromField: 'following',
    connectToField: 'follower',
    maxDepth: 1,
    as: 'connections'
  }},
  { $unwind: { path: '$connections' }},
  { $group: {
    _id: '$connections.follower',
    follows: {
      $addToSet: '$connections.following'
    }
  }},
  { $unwind: { path: '$follows' }},
  { $group: {
    _id: '$follows',
    isFollowedBy: {
      $addToSet: '$_id'
    }
  }},
  { $match: { isFollowedBy: { $not: { $in: [1] }} }},
  { $group: {
    _id: null,
    newConnections: {
      $addToSet: '$_id'
    }
  }},
  { $project: { _id: 0 }}
])

请注意,这个管道最终从另一个集合中间构建关系,因此另一个方法是从另一个集合开始,如下所示:

代码语言:javascript
复制
db.follows.aggregate([
  { $lookup: {
    from: 'follows',
    localField: 'following',
    foreignField: 'follower',
    as: 'potentialSet'
  }},
  { $unwind: {
    path: "$potentialSet",
    preserveNullAndEmptyArrays: true
  }},
  { $group: {
    _id: "$follower",
    "alreadyFollowing": {
      $addToSet: "$following"
    },
    "potentialConnections": {
      "$addToSet": "$potentialSet.following"
    }
  }},
  { $project: {
    newConnections: { $setDifference: [ "$potentialConnections", "$alreadyFollowing" ] }
  }},
  { $match: { _id: 1 }},
  { $project: { _id: 0 }}
])

如果有帮助的话,我使用MongoDB指南针社区版来帮助构建这些管道。它非常酷,因为它允许您快速迭代并查看每个阶段的输出,这在调试管道时确实有帮助。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53572226

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档