我目前正在Java Web应用程序中使用MongoDB的聚合框架,以根据其他用户的偏好为用户生成推荐。
我正在使用的一种主要方法是查看数组交集。
现在我的算法只考虑两个用户“相似”,如果他们有一个非零的数组交集。
为了构建更准确的算法,我想将集合交集的大小权衡到我的聚合管道中。
有办法做到这一点吗?
答案 0 :(得分:3)
如果我理解您的问题,您的数据类似于以下内容:
db.users.insert({_id: 100, likes: [
'pina coladas',
'long walks on the beach',
'getting caught in the rain'
]})
db.users.insert({_id: 101, likes: [
'cheese',
'bowling',
'pina coladas'
]})
db.users.insert({_id: 102, likes: [
'pina coladas',
'long walks on the beach'
]})
db.users.insert({_id: 103, likes: [
'getting caught in the rain',
'bowling'
]})
db.users.insert({_id: 104, likes: [
'pina coladas',
'long walks on the beach',
'getting caught in the rain'
]})
并且您希望为给定用户计算他们与其他用户有多少匹配功能(在此示例中为“喜欢”)?以下聚合管道将实现此目的:
user = 100
user_likes = db.users.findOne({_id: user}).likes
return_only = 2 // number of matches to return
db.users.aggregate([
{$unwind: '$likes'},
{$match: {
$and: [
{_id: {$ne: user}},
{likes: {$in: user_likes}}
]
}},
{$group: {_id: '$_id', common: {$sum: 1}}},
{$sort: {common: -1}},
{$limit: return_only}
])
鉴于上面的示例输入数据,将输出以下结果,显示前2个匹配项:
{
"result" : [
{
"_id" : 104,
"common" : 3
},
{
"_id" : 102,
"common" : 2
}
],
"ok" : 1
}
请注意,我认为您只需要排名前所未有的匹配项,因为可能会有非常多的用户。 $ limit步骤后跟$ limit步骤将完成此操作。如果不是这种情况,那么您可以省略管道中的最后两个步骤。
我希望这有帮助!如果您还有其他问题,请与我们联系。
布鲁斯
答案 1 :(得分:1)
从MongoDB 2.6+开始,您可以使用$size表达式。
如果您正在进行两个数组(集合)的交集,则首先要使用$setIntersection运算符来查找两个数组的交集。另一个例子在this question中给出。
然后,您可以使用新的$size运算符来获取管道交叉阶段输出的大小。 This answer提供了使用新的$ size表达式的示例。