Darko Romanov
Darko Romanov

Reputation: 2805

MongoDB find documents if a property array doesn't contain an object

I have a list of documents like this.

[
  {
     "name" : "test",
     "data" : [
         { "code" : "name", "value" : "Diego" },      
         { "code" : "nick", "value" : "Darko" },      
         { "code" : "special", "value" : true }
     ]
  },
  {
     "name" : "another",
     "data" : [
         { "code" : "name", "value" : "Antonio" },      
         { "code" : "nick", "value" : "Tony" }
     ]
  }
]

now I need to find all the documents that:

a) don't contain a "data" item with code "special"

OR

b) contains a "data" item with code "special" and value false

It's like I needed the opposite of $elemMatch or I'm missing something?

Upvotes: 6

Views: 4689

Answers (2)

wdberkeley
wdberkeley

Reputation: 11671

I'm assuming that you're inserting each document in your list of documents as a separate member of a collection test.

For a,

db.test.find({ "data.code" : { "$ne" : "special" } })

For b.,

db.test.find({ "data" : { "$elemMatch" : { "code" : "special", "value" : false } } })

Combining the two with $or,

db.test.find({ "$or" : [
    { "data.code" : { "$ne" : "special" } },
    { "data" : { "$elemMatch" : { "code" : "special", "value" : false } } }
] })

Upvotes: 10

Abhi
Abhi

Reputation: 6568

Hope this $nin will solve your issues. I insertd your docs into "so" collection

db.so.find({}).pretty();

{
        "_id" : ObjectId("5489cd4f4cb16307b808d4b2"),
        "name" : "test",
        "data" : [
                { "code" : "name",
                  "value" : "Diego"
                },
                { "code" : "nick",
                  "value" : "Darko"
                },
                { "code" : "special",
                  "value" : true
                }
        ]
}
{
        "_id" : ObjectId("5489cd674cb16307b808d4b3"),
        "name" : "another",
        "data" : [
                {"code" : "name",
                 "value" : "Antonio"
                },
                { "code" : "nick",
                  "value" : "Tony"
                }
        ]
}

don't contain a "data" item with code "special"

> db.so.find({"data.code":{$nin:["special"]}}).pretty();
{
        "_id" : ObjectId("5489cd674cb16307b808d4b3"),
        "name" : "another",
        "data" : [
                { "code" : "name",
                  "value" : "Antonio"
                },
                { "code" : "nick",
                  "value" : "Tony"
                }
        ]
}

contains a "data" item with code "special" and value false

db.so.find({$and:[{"data.code":"special"},{"data.value":false}]}).pretty();

Upvotes: 0

Related Questions