andr111
andr111

Reputation: 3052

Mongodb find a document with all subdocuments satisfying a condition

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

Answers (3)

pcorey
pcorey

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

Asya Kamsky
Asya Kamsky

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

yaara4
yaara4

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

Related Questions