Вопрос

I read the Voting with Atomic Operators article. In this article, the voters field is an array of ObjectIds. But I would like to store the voters as an array of embedded documents with the following format:

{
  user: ObjectId,
  date: Date,
  isDownvote: Boolean,  // If false, it's an upvote.
}

The user can upvote or downvote the post just like the voting system provided by Stack Overflow. So, for example, when the user want to upvote a post, there are cases to consider:

  • If a downvote by the user already exists, then update the vote's isDownvote to false.
  • Else push a new vote with isDownvote being false.

How can I push/pull a vote in single query with this format of votes?

Это было полезно?

Решение

Another way of doing this fully atomically is:

db.posts.update({'_id':post_id}, {
    '$pull': {'votes.user':ObjectId},
    '$addToSet': {votes: {
        user: objectId,
        date: Date,
        isdownvote: isdownvote
    }}
})

As already said, there is no upsert for subdocuments so this kind of cheats and deletes the old vote and writes it again. The date field should still be ok because if the user votes again then the date field should change to the last time that user voted so in my mind that part makes sense.

Другие советы

$push : { voters : {
  user: ObjectId,
  date: Date
}}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top