MongoDB - 查询获取项目,也知道我是否投票

时间:2013-09-12 16:52:33

标签: mongodb aggregation-framework

这个问题与此问题有关: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} })

2 个答案:

答案 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步骤不会 允许该文档通过管道的其余部分,所以你不会 知道给定的用户没有投票。这将是一个问题 还试图对你的第一个提议进行聚合查询 架构,因为直觉上我们必须在$unwindupVotersdownVoters,如果其中一个数组是空的,那么 文件不会通过管道。

如果您尝试访问用户经常投票的内容,那么就是这样 可能值得以某种方式存储投票,允许你建立 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_iditem_id上的索引也可能是一个更快的选择 {{1}}。

答案 1 :(得分:0)

就在我的脑海中,你可能需要放松upVoters和downVoters数组,然后再做一场比赛,其中包括:

db.votes.aggregate([
  {$unwind: "$upVoters"},
  {$group: {"_id": "upVoters"}},
  {$match:{"_id.upVoters": {"$in": [2]}}}
])

(我大约99%肯定你需要稍微修改:))