以primefaces方式更新数组项

基本问题:

我怎样才能检查一个文档的子数组,看看是否存在一个条目,更新它,如果它没有,或者添加它,如果它不是primefaces的方式? 我也想自动调整计数器(使用$inc ),具体取决于第一个操作的结果。

完整的解释:

我试图写一个方法来为任意的mongodb文档提供primefaces的“upvote”或“downvote”function。

我想要发生的是以下几点:

  • 将“投票”和“投票评分”项添加到给定的模式
  • “投票”是由选举人的投票types(向上或向下)和userId组成的一组对象
  • “voteScore”是所有选票的总和(+1为upvote,-1为downvote)

我试图实现的逻辑是:

  • 当用户投了一个向上或向下的投票,然后使用primefaces$inc操作符相应地更新“voteScore”,并使用该用户的ID和投票types将新的投票添加到数组中。
  • 当用户改变他/她的投票时,voteScore会自动更新,投票将从数组中删除(如果voteType"none" ),或者更改voteType以反映更改。

我怎么去做这个? 我假设我将不得不使用ether document.update()model.findOneAndUpdate() ,因为传统的MongooseArray方法 (后跟save() )不会是primefaces的。

到目前为止,我有下面的代码,但它不工作:

 var mongoose = require('mongoose'); var voteTypes = ['up', 'down']; var voteSchema = new mongoose.Schema({ userId: { type: Schema.Types.ObjectId, ref: 'User', }, voteType: { type: String, enum: voteTypes } }); exports.schema = voteSchema; exports.plugin = function votesPlugin(schema, options) { schema.add({ voteScore: Number }); schema.add({ votes: [voteSchema] }); schema.methods.atomicVote = function(args, callback) { var item = this; var voteType = (args.voteType && args.voteType.toLowerCase()) || 'none'; var incrementScore, query; switch (voteType) { case 'none': incrementScore = -voteTypeValue(voteRemoved.voteType); query = this.update({ $inc: {voteScore: incrementScore}, $pull: { votes: { userId: args.userId } } }); break; case 'up': case 'down': var newVoteVal = voteTypeValue(args.voteType); if (/* Vote does not already exist in array */) { incrementScore = newVoteVal; query = this.update({$inc: {voteScore: incrementScore}, $addToSet: { userId: args.userId, voteType: args.voteType }); } else { var vote = /* existing vote */; if (vote.voteType === args.voteType) return callback(null); // no-op var prevVoteVal = voteTypeValue(vote.voteType); incrementScore = (-prevVoteVal) + newVoteVal; vote.voteType = args.voteType; // This likely won't work because document.update() doesn't have the right query param // to infer the index of '$' query = this.update({$inc: {voteScore: incrementScore}, $set: { 'votes.$': { userId: args.userId, voteType: args.voteType } }); } break; default: return callback(new Error('Invalid or missing "voteType" argument (possible values are "up", "down", or "none").')); } query.exec(callback); }; }; function voteTypeValue(voteType) { switch (voteType) { case 'up': return 1; case 'down': return -1; default: return 0; } } 

要做到这一点primefaces上你最好分开arrays“上/下”的选票。 通过这种方式,您可以同时从每个字段中$push$pull 。 这很大程度上是由于MongoDB无法在文档中的相同字段path上的单个更新中执行这些操作。 试图这样做会导致错误。

简化的模式表示可能如下所示:

 var questionSchema = new Schema({ "score": Number, "upVotes": [{ type: Schema.Types.ObjectId }], "downVotes": [{ type: Schema.Types.ObjectId }] ]); module.exports = mongoose.model( 'Question', questionSchema ); 

这是一个普遍的表示,所以不要太直接,但重点是两个数组。

当处理“upvote”时,你真正需要做的就是确保你没有添加到“upvotes”数组中已经存在的“user”

 Question.findOneAndUpdate( { "_id": question_id, "upVotes": { "$ne": user_id } }, { "$inc": { "score": 1 }, "$push": { "upVotes": user_id }, "$pull": { "downVotes": user_id } }, function(err,doc) { } ); 

而反过来处理“downvote”:

 Question.findOneAndUpdate( { "_id": question_id, "downVotes": { "$ne": user_id } }, { "$inc": { "score": -1 }, "$push": { "downVotes": user_id }, "$pull": { "upVotes": user_id } }, function(err,doc) { } ); 

有了这个合乎逻辑的扩展,你可以通过简单地从这两个数组中“拉”来取消所有选票。 但是,你确实可以对此“聪明”一些,并在应用程序中维护“状态”信息,所以如果你正在递增或递减“分数”,你就“知道”了。

所以对于我来说,我会这样做,并且在发送响应时处理“数组”结果,只是将状态信息过滤掉当前的“用户”,这样在取消甚至不发送请求时就可以做出明智的select该用户已经投下“upvote”或“downvote”的服务器,情况可能如此。

还要注意$addToSet在这里不是没有查询的选项,因为$inc独立于其他操作符运行。 所以你不想“select”一个不适合更新的文档。