模型架构
const PollSchema = new Schema({
title: { type: String, trim: true, required: true },
choices: [
{
title: { type: String, trim: true, required: true },
votes: { type: Number, default: 0, min: 0 },
}
],
date: { type: Date, default: Date.now },
url: { type: String, required: true, unique: true },
})
更新电话
async vote (pollId, choiceId, unvoteId = '') {
try {
await pollModel.update(
{ '_id': pollId, 'choices._id': choiceId },
{ $inc: { 'choices.$.votes': 1 } },
)
if (unvoteId) {
await pollModel.update(
{
"$and": [
{ '_id': pollId },
{ 'choices._id': unvoteId },
{ 'choices.votes': { $gt: 0 } }
],
},
{ $inc: { 'choices.$.votes': -1 } },
)
}
return await pollModel.findById(pollId)
} catch (e) {
throw new ApiError(
500, 'Error: Poll:Vote', e
)
}
}
我一直在尝试过多的组合尝试让它发挥作用。投票+1按预期工作,但在尝试-1时,查询条件未正确匹配。我尝试了$and
,$elemMatch
,带有3个条件的普通对象(根据文档,这是足够的,并且隐含地意味着and
。
每当我通过unvoteId发送时,无论我在数组中选择哪个_id
,它都将始终匹配具有$gt 0
个投票的FIRST元素。好像choices._id
被完全忽略,并且只要它符合选项> 0票,它返回$
位置参数的那个。
这是打算吗?我假设只有满足所有3个条件才会$and
匹配。
我想要做的是使用$inc
以原子方式更新投票,同时还确保当有人投票时,他们不能将值低于0.因为猫鼬验证器在更新期间没有运行,我是试图通过查询本身验证这一点。
答案 0 :(得分:1)
尝试这样的事情。
pollModel.update({
_id: pollId,
choices: {
$elemMatch: {
_id: unvoteId,
votes: {
$gt: 0
}
}
}
}, {
$inc: {
"choices.$.votes": -1
}
})