这个问题与此问题有关:simple voting system with MongoDB
我有一系列可以由用户进行投票或投票的项目。我想知道如何检索一些物品,同时知道我是否投票了。
项目集合包含或多或少类似的项目:
{
_id:0,
name:'Item 0',
upVoters: [ 1, 2 ],
downVoters: [ 3, 4 ]
}
{
_id:1,
name:'Item 1',
upVoters: [ 1, 3 ],
downVoters: [ 4 ]
}
{
_id:2,
name:'Item 2',
upVoters: [ ],
downVoters: [ 2 ]
}
这意味着,例如,项目0由具有ID 1和2的用户进行投票,并由用户3和4进行投票。
如果我是用户2并获得这些项目,我想知道我投票的第0项,没有投票第1项和投票第2项。
我该如何执行该查询?如果可能的话,我想只用一个查询来做。我想我必须使用聚合,但我找不到这样做的方法。
如果我从用户2的角度查询项目,则会产生预期结果:
{
_id:0,
name:'Item 0',
user_vote: 1
}
{
_id:1,
name:'Item 1',
user_vote: 0
}
{
_id:2,
name:'Item 2',
user_vote: -1
}
如果有帮助,我可以改变收藏形状。例如,我可以使用类似于上面链接的问题中提出的模型。
替代型号:
{
_id:0,
name:'Item 0',
voters: [
{ id:1, vote:+1}, { id:2, vote:+1},
{ id:3, vote:-1}, { id:4, vote:-1}
]
}
{
_id:1,
name:'Item 1',
voters: [
{ id:1, vote:+1}, { id:3, vote:+1},
{ id:4, vote:-1}
]
}
{
_id:2,
name:'Item 2',
voters: [
{ id:2, vote:-1}
]
}
非常感谢
- 费兰
编辑:
正如我在评论中所说,到目前为止我找到的解决方案是发送3个查询:一个用于获得投票的项目,另一个用于获得投票,另一个用于获得非投票:< / p>
为用户提供项目和投票的临时解决方案
db.items.find({ upVoters:USER_ID })
db.items.find({ downVoters:USER_ID })
db.items.find({ upVoters:{$ne:USER_ID}, downVoters:{$ne:USER_ID} })
答案 0 :(得分:4)
如果您将第二个示例用作架构,则可以执行以下聚合:
db.coll2.aggregate([
// Split items by vote
{$unwind:"$voters"},
// Set vote to "0" for votes the user didn't cast
{$project:{"vote":{$cond:[{$eq:["$voters.id",2]},"$voters.vote",0]}}},
// Sum the votes for each item for this user (will get rid of 0-vote if user actually voted)
{$group:{"_id":"$_id", "vote":{$sum:"$vote"}}}])
实现您正在寻找的结果。有一点需要注意的是
如果某个项目没有投票,则$unwind
步骤不会
允许该文档通过管道的其余部分,所以你不会
知道给定的用户没有投票。这将是一个问题
还试图对你的第一个提议进行聚合查询
架构,因为直觉上我们必须在$unwind
上upVoters
和downVoters
,如果其中一个数组是空的,那么
文件不会通过管道。
如果您尝试访问用户经常投票的内容,那么就是这样
可能值得以某种方式存储投票,允许你建立
user_id
和/或item_id
上的索引(聚合查询
以上不能利用索引)。你可以存储投票
他们自己的集合,例如:
{
item_id:0,
user_id:1,
vote:1
}
{
item_id:0,
user_id:4,
vote:-1
}
{
item_id:2,
user_id:2,
vote:-1
}
这使您可以在不进行聚合的情况下提取所需的数据
user_id
和item_id
上的索引也可能是一个更快的选择
{{1}}。
答案 1 :(得分:0)
就在我的脑海中,你可能需要放松upVoters和downVoters数组,然后再做一场比赛,其中包括:
db.votes.aggregate([
{$unwind: "$upVoters"},
{$group: {"_id": "upVoters"}},
{$match:{"_id.upVoters": {"$in": [2]}}}
])
(我大约99%肯定你需要稍微修改:))