让我们说我有一个用户集合,每个用户都有一个他喜欢的网页数组(想象一下facebook页面ID):
当前用户:
{
name: "me",
likes: [123,234,777]
}
目标列表:
{
name: "Jane",
likes: [111,222,333]
},
{
name: "Mary",
likes: [567,234,777,654]
},
{
name: "John",
likes: [123,234,567,890,777]
},
{
name: "Steve",
likes: [666,777,321,432,543]
},
结果:
{
name: "John",
likes: [123,234,777]
},
{
name: "Mary",
likes: [234,777]
},
{
name: "Steve",
likes: [777]
},
{
name: "Jane",
likes: []
},
我想得到一个被我最喜欢的用户订购的用户反应性出版物。我需要反应,因为每个用户都有用户存在 - 在线/离线。喜欢id的数组是静态的,但用户存在随时间而变化。
答案 0 :(得分:1)
我将把发布/订阅和被动部分留给您,但是可以使用聚合框架来执行 set-intersection 而不必在代码中迭代结果的一般机制。
值得注意的是,这只是服务器端功能,您需要获取对底层“节点本机驱动程序”的引用,以便在当前调用.aggregate()
方法:
var db = MongoInternals.defaultRemoteCollectionDriver().mongo.db;
事实上,对于MongoDB 2.6及更高版本,有一个$setIntersection
运算符可用于实现这一点:
db.targets.aggregate([
// You probably want a $match to find "friends" first
{ "$match": { "_id": { "$in": [ friends ] } } },
// Project the set intersection
{ "$project": {
"name": 1,
"likes": {
"$setIntersection": [ "$likes", [123,234,777] ]
}
}}
])
对于2.6之前的MongoDB版本,基本上仍然可以,你只需要手动完成$setIntersection
运营商允许的所有工作:
db.targets.aggregate([
// You probably want a $match to find "friends" first
{ "$match": { "_id": { "$in": [ friends ] } } },
// Project an array with the matching values
{ "$project": {
"name": 1,
"likes": 1,
"mylikes": { "$cond": [ 1, [123,234,777], 0 ] }
}},
// Unwind both of the arrays
{ "$unwind": "$likes" },
{ "$unwind": "$mylikes" },
// Work out where those likes are the same. Intersection.
{ "$project": {
"name": 1,
"likes": 1,
"match": { "$eq": [ "$likes", "$mylikes" ] }
}},
// Filter the results that did not match
{ "$match": { "match": true } },
// Group back the array of likes
{ "$group": {
"_id": "$_id",
"name": { "$first": "$name" },
"likes": { "$push": "$likes" }
}}
])
最后一个删除了“Jane”的条目,因为没有匹配的喜欢,但或多或少是所需的结果。
如果您对此感兴趣,那么您应该查看this post,其中更详细地介绍了使用聚合与流星。但是这里的一般方法应该提供比在客户端处理结果更快捷,更优雅的解决方案,以便找到集合的交集。