所以我在 MongoDB (2.6.4) 中有一个查询,我试图在其中实现一个简单的 upvote/downvote 机制。当用户单击 upvote 时,我需要执行以下操作:
到目前为止,我形成的查询(不正确)是:
db.collection.aggregate([
{
$project: {
"_id" : ObjectId("53e4d45c198d7811248cefca"),
"upvote": {
"$cond":
[
{"$in": ["$upvote",1] },
{"$pull": {"upvote" : 1}},
{"$addToSet": {"upvote" : 1}, "$pull": {"downvote": 1}}
]
}
}
}
])
其中“1”是尝试投票的用户 ID。upvote
和 downvote
都是数组,它们分别包含已投赞成票和反对票的用户的用户 ID。对于查询的输出,我只想要一个 bool 值:
true
如果 $cond
评估为 true
,否则为 false
。 最佳答案
这不是实现赞成票和反对票的好方法。除了聚合框架不是以任何方式更新文档的机制之外,由于您想要实现的逻辑,您似乎倾向于认为它可能是一个解决方案。但聚合不更新。
你想要什么,我们称之为“问题”模式是这样的结构:
{
"_id": ObjectId("53f51a844ffa9b02cf01c074"),
"upvoted": [],
"downvoted": [],
"upvoteCount": 0,
"downvoteCount": 0
}
这可以很好地与原子更新一起使用,并且实际上同时为您提供有关对象的一些状态信息。
对于“upvoted”和“downvoted”数组,我们将考虑“users”投票具有相似的唯一 ObjectId 值。所以我们要做的是从任何一个数组中获取
$push
或 $pull
,并且“递增/递减”计数器值以及这些操作中的每一个。以下是投票的工作原理:
db.questions.update(
{
"_id": ObjectId("53f51a844ffa9b02cf01c074"),
"upvoted": { "$ne": ObjectId("53f51c0a4ffa9b02cf01c075") }
"downvoted": ObjectId("53f51c0a4ffa9b02cf01c075")
},
{
"$push": { "upvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
"$inc": { "upvoteCount": 1, "downvoteCount": -1 },
"$pull": { "downvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
}
)
db.questions.update(
{
"_id": ObjectId("53f51a844ffa9b02cf01c074"),
"upvoted": { "$ne": ObjectId("53f51c0a4ffa9b02cf01c075") }
},
{
"$push": { "upvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
"$inc": { "upvoteCount": 1 },
}
)
实际上,这是两个操作,您也可以使用 Bulk operations AP I 进行操作(实际上可能是最好的方法),但它有其意义。第一个语句将只匹配当前用户在数组中记录了“downvote”的文档。因此,我们已经将该用户 id 值“推送”到“downvotes”数组中。如果不存在,则不进行更新。但是您既可以从各自的数组中推拉,也可以同时“递增/递减”计数器字段。
使用第二个语句只匹配第一个不匹配的内容,您可以做出公平的评估,现在您不需要触摸“downvotes”而只需处理 upvote 字段。在这两种情况下,安全的做法是确保主要条件是当前用户 id 值不存在于“upvoted”数组中。
对于downvotes,字段只是颠倒了:
db.questions.update(
{
"_id": ObjectId("53f51a844ffa9b02cf01c074"),
"downvoted": { "$ne": ObjectId("53f51c0a4ffa9b02cf01c075") }
"upvoted": ObjectId("53f51c0a4ffa9b02cf01c075")
},
{
"$pull": { "upvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
"$inc": { "upvoteCount": -1, "downvoteCount": 1 },
"$push": { "downvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
}
)
db.questions.update(
{
"_id": ObjectId("53f51a844ffa9b02cf01c074"),
"downvoted": { "$ne": ObjectId("53f51c0a4ffa9b02cf01c075") }
},
{
"$push": { "downvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
"$inc": { "downvoteCount": 1 },
}
)
自然地,您可以看到简单地取消相关用户的任何“赞成/反对”的逻辑进展。如果您希望并公开客户端中的信息,不仅可以显示当前用户是否已经“赞成/反对”,而且还可以控制点击操作并消除不必要的请求,那么您也可以聪明一点。
关于mongodb - 如果不存在则插入,否则删除 MongoDB,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25421164/