我收集了“谁在跟踪谁”(如Instagram):
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 }
]);我试图向其他用户推荐他们可以跟踪的其他用户。例如,他们可以跟踪哪些其他人;建议的追随者,根据现有的共同联系的数量排序。
在本例中:
+--------+--------------+----------+
| A | is following | B |
+--------+--------------+----------+
| Arnold | -> | James |
| Arnold | -> | Harrison |
| James | -> | Jennifer |
| James | -> | Harrison |
+--------+--------------+----------+阿诺德和詹姆斯之间的,谁能跟随阿诺德?(不包括现有的连接)
The answer should be: Jennifer这是一次失败的尝试:
db.users.aggregate([
{
$match: { _id: 1 } // Arnold
},
{
$graphLookup: {
from: "follows",
startWith: "$_id",
connectFromField: "following",
connectToField: "follower",
maxDepth: 1,
as: "connections",
}
}
]);其结果是:
{
"_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
}
]
}我想我需要做一些放松,但我现在有点卡住了
发布于 2018-12-02 11:56:19
以下是两种可能的方法。(我还没有用更大的数据集进行测试,所以您的里程可能会有所不同!)
第一个构建在您的$graphLookup阶段上:
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 }}
])请注意,这个管道最终从另一个集合中间构建关系,因此另一个方法是从另一个集合开始,如下所示:
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指南针社区版来帮助构建这些管道。它非常酷,因为它允许您快速迭代并查看每个阶段的输出,这在调试管道时确实有帮助。
https://stackoverflow.com/questions/53572226
复制相似问题