0

I have a collection called collectionA that contains an array of type objects.

Example:

{
"_id" : ObjectId("123456"),
"tags" : [ 
    {
        "name" : "Bob D",
    }, 
    {
        "name" : "another name",
    }
    ...

How would I write a query that matches the name within the array of objects? I've tried db.getCollection('collectionA').find({ "name": "Bob D}) but that didn't work.

mickl
  • 48,568
  • 9
  • 60
  • 89
Stackimus Prime
  • 159
  • 1
  • 15
  • 1
    Could you add sample document from your collection and expected output ? – mickl Oct 03 '18 at 15:48
  • 2
    Try `db.getCollection('collectionA').find({ "tags.name": "Bob D" })` since `name` is nested inside `tags` – mickl Oct 03 '18 at 16:02
  • @mickl I've tried your command except I'm getting back the entire object (objectId(123456)) instead of the individual objects within the tags array that name matches to – Stackimus Prime Oct 03 '18 at 16:17

1 Answers1

2

To filter nested array you can either use $elemMatch (as projection):

db.col.find({ "tags.name": "Bob D" }, { tags: { $elemMatch: { name: "Bob D" } } })

which returns first matching array element, or use $filter to get multiple matching elements of tags array:

db.col.aggregate([ { $addFields: { tags: { $filter: { input: "$tags", as: "tag", cond: { $eq: [ "$$tag.name", "Bob D" ] } } } } } ])
mickl
  • 48,568
  • 9
  • 60
  • 89
  • Thanks a lot! Both methods work. – Stackimus Prime Oct 03 '18 at 16:46
  • Actually, to build off that, why do you need tags: { $elemMatch: { name: "Bob D" } in addition to db.col.find({ "tags.name": "Bob D" }? I know if I don't include elemMath, I get back the entire document instead of just the objects that matches with name. – Stackimus Prime Oct 03 '18 at 17:09
  • Second argument of `find()` represents a projection which allows you to reshape the document you store in your db – mickl Oct 03 '18 at 17:13