Reputation: 3052
I have Game collection in my DB:
var game = {
players: [{username:"user1", status:"played"},
{username:"user2", status:"accepted"}]
}
As far as I understand query like this: db.games.find({"players.status":"played"})
will give me all games where at least one player has status "played". How can I find games with ALL players having status "played"?
Upvotes: 10
Views: 13352
Reputation: 850
I ran into this problem too. I was trying to use $all
and making little to no progress. It helped to flip my perspective on the problem and use $not
instead. I wrote about what I found here.
In your situation, you should be able to do something like this:
db.games.find({
players: {
$not: {
$elemMatch: {
status: { $ne: "played" }
}
}
}
})
Find all documents with a player status not equal to "played"
and return the inverse of that set. The nice thing about this is that you never have to worry about adding more status values.
Upvotes: 0
Reputation: 42352
If you only have one other status than "played" use the query:
db.games.find({ "players.status": { $ne:"accepted" } })
You can adjust the query to handle more status values, as long as they are all known at the time of the query.
Upvotes: 13
Reputation: 304
Use the $unwind feature of the aggregation framework:
db.collection.aggregate([{$unwind:"$players.status"},{$match:{"players.status":"played"},{$project:{"_id":0,"players.status":1}}])
(check out this answer: https://stackoverflow.com/a/15082321/1214167)
Upvotes: -1