user1760020
user1760020

Reputation: 99

Querying MongoDB for an Object nested in an Array

I have a User schema that looks like this:

{
    "_id" : ObjectId("5f0cbcdf8363cd155c2570f5"),
    "clients" : [ 
        {
            "clientName" : "Chabad of Closter",
            "activeInvoice" : [ 
                {
                    "clientName" : "Chabad of Closter",
                    "startTime" : "2020-07-16T03:06:19.102Z",
                    "endTime" : "2020-07-16T06:06:19.102Z",
                    "duration" : "3.00",
                    "rate" : "25",
                    "description" : "email",
                    "total" : "$75.00"
                }, 
                {
                    "clientName" : "Chabad of Closter",
                    "startTime" : "2020-07-20T18:49:45.300Z",
                    "endTime" : "2020-07-20T20:49:45.300Z",
                    "duration" : "2.00",
                    "rate" : "25",
                    "description" : "janitor",
                    "total" : "$50.00"
                }, 
                {
                    "clientName" : "Chabad of Closter",
                    "startTime" : "2020-07-20T08:02:04.795Z",
                    "endTime" : "2020-07-20T21:02:04.795Z",
                    "duration" : "13.00",
                    "rate" : "35",
                    "description" : "something",
                    "total" : "$455.00"
                }
            ],
            "pastInvoices" : []
        }, 
        {
            "clientName" : "Chabad UC",
            "activeInvoice" : [ 
                {
                    "clientName" : "Chabad UC",
                    "startTime" : "2020-07-14T00:43:30.689Z",
                    "endTime" : "2020-07-14T03:43:30.689Z",
                    "duration" : "3.00",
                    "rate" : "25",
                    "description" : "website",
                    "total" : "$75.00"
                }, 
                {
                    "clientName" : "Chabad UC",
                    "startTime" : "2020-07-14T00:43:30.689Z",
                    "endTime" : "2020-07-14T03:43:30.689Z",
                    "duration" : "3.00",
                    "rate" : "25",
                    "description" : "website",
                    "total" : "$75.00"
                }, 
                {
                    "clientName" : "Chabad UC",
                    "startTime" : "2020-07-16T08:32:44.980Z",
                    "endTime" : "2020-07-16T08:32:44.980Z",
                    "duration" : "0.00",
                    "rate" : "25",
                    "description" : "something",
                    "total" : "$0.00"
                }, 
                {
                    "clientName" : "Chabad UC",
                    "startTime" : "2020-07-20T20:22:27.399Z",
                    "endTime" : "2020-07-20T20:22:27.399Z",
                    "duration" : "0.00",
                    "rate" : 0,
                    "description" : "",
                    "total" : "$0.00"
                }
            ],
            "pastInvoices" : []
        }, 
        {
            "clientName" : "Chabad Mobile",
            "activeInvoice" : [ 
                {
                    "clientName" : "Chabad Mobile",
                    "startTime" : "2020-07-14T04:05:18.084Z",
                    "endTime" : "2020-07-14T06:05:18.084Z",
                    "duration" : "2.00",
                    "rate" : "25",
                    "description" : "Fema grant",
                    "total" : "$50.00"
                }, 
                {
                    "clientName" : "Chabad UC",
                    "startTime" : "2020-07-16T04:56:51.451Z",
                    "endTime" : "2020-07-16T05:56:51.451Z",
                    "duration" : "1.00",
                    "rate" : "25",
                    "description" : "grants",
                    "total" : "$25.00"
                }, 
                {
                    "clientName" : "Chabad of Closter",
                    "startTime" : "2020-07-16T03:56:51.451Z",
                    "endTime" : "2020-07-16T05:56:51.451Z",
                    "duration" : "2.00",
                    "rate" : "26",
                    "description" : "grants",
                    "total" : "$52.00"
                }, 
                {
                    "clientName" : "Chabad Mobile",
                    "startTime" : "2020-07-15T18:51:00.000Z",
                    "endTime" : "2020-07-16T08:09:20.001Z",
                    "duration" : "13.31",
                    "rate" : "22",
                    "description" : "website",
                    "total" : "$292.82"
                }
            ],
            "pastInvoices" : []
        }
    ],
    "username" : "[email protected]",
    "password" : "************************************",
    "firstName" : "John",
    "__v" : 0
}

I'm trying to query the "clients" array with a value from the "clientName" property.

app.get("/closeinvoice", function(req, res){
  // gets the id for the document
  const id = req.user._id;
  // gets the value of "clientName" for the query
  const c = req.query.client;

  User.find({_id: id, "clients.clientName": c}, function(err, foundDoc) {
    if (err) {
      console.log(err)
    } else {
      console.log(foundDoc);
    }
  })
})

Each time I do this, MongoDB returns the entire document. I need it to return only one object from the nested array. I'm also wondering if I could be using a different method from the Mongoose API. I would prefer to use "findByID" but I'm not sure if you can for this type of query.

Upvotes: 1

Views: 40

Answers (1)

mickl
mickl

Reputation: 49985

You can take advantage of the $ (projection) operator which returns the first matching element from an array (based on corresponding `$elemMatch):

User.find({ _id: id, clients: { $elemMatch: { clientName: c }}}, { "clients.$": 1}, function(err, foundDoc) { ... })

Mongo Playground

Upvotes: 1

Related Questions