I’m trying to make a MongoDB database for a simple voting system. If I were to draw a schema, then it looks something like this:
User {
name: String
, email: String
}
Vote {
message: String
, voters: [ObjectId(User._id)]
}
I have some questions about this design when there are a lot of voters for one vote:
- Sending the whole voters array to the client’s side (not to mention caching it in memory) is very expensive, right? Is there a way to get the Vote in a “shallow” way, so when I need vote.voters, it will make another database request to the array of voters?
- If a voter has voted already, I want to check that and not count his vote. To do that, is there a query I can run in the array of embedded voters to quickly find this?
- When showing votes, I’d want to show the number of votes without fetching the voters array to the client side. Is there some kind of count query I can run to count the voters length?
I would add a bit of redundancy to the schema to avoid some of the potential problems you mention. I assume you want to 1) quickly count the number of votes and 2) make sure a user cannot vote twice.
One way to achieve this is to keep both a list of users and a count of votes, and add a clause to the update query that makes sure that a vote is only added if the user’s ID is not in the list of voters:
(the last parameter is
upsert, a very nice feature of Mongo)Then, if you want to show the number of votes you can limit the properties of the result to the
votesproperty:You can find a complete description of more or less exactly what you want to do here: http://cookbook.mongodb.org/patterns/votes/