Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unwind array of objects mongoDB

My collection contains the following two documents

{
      "BornYear": 2000,
      "Type": "Zebra",
      "Owners": [
        {
          "Name": "James Bond",
          "Phone": "007"
        }
      ]
    }

    {
      "BornYear": 2012,
      "Type": "Dog",
      "Owners": [
        {
          "Name": "James Brown",
          "Phone": "123"
        },
        {
          "Name": "Sarah Frater",
          "Phone": "345"
        }
      ]
    }

I would like to find all the animals whichs have an owner called something with James. I try to unwind the Owners array, but cannot get access to the Name variable.

like image 243
CruelIO Avatar asked Dec 25 '22 00:12

CruelIO


1 Answers

Bit of a misnomer here. To just find the "objects" or items in a "collection" then all you really need to do is match the "object/item"

db.collection.find({
    "Owners.Name": /^James/
})

Which works, but does not of course limit the results to the "first" match of "James", which would be:

db.collection.find(
    { "Owners.Name": /^James/ },
    { "Owners.$": 1 }
)

As a basic projection. But that does not give any more than a "single" match, which means you need the .aggregate() method instead like so:

db.collection.aggregate([
    // Match the document
    { "$match": {
        "Owners.Name": /^James/
    }},

    // Flatten  or de-normalize the array
    { "$unwind": "Owners" },


    // Filter th content
    { "$match": {
        "Owners.Name": /^James/
    }},

    // Maybe group it back
    { "$group": {
        "_id": "$_id",
        "BornYear": { "$first": "$BornYear" },
        "Type": { "$first": "$Type" },
        "Ownners": { "$push": "$Owners" }
    }}
])

And that allows more than one match in a sub-document array while filtering.

The other point is the "anchor" or "^" caret on the regular expression. You really need it where you can, to make matches at the "start" of the string where an index can be properly used. Open ended regex operations cannot use an index.

like image 83
Neil Lunn Avatar answered Jan 14 '23 06:01

Neil Lunn