dhShin
dhShin

Reputation: 31

how can I get one document in mongoose?(don't use aggregate)

I want to return one index's object of the array, but when I query, It returns to me that all of the documents.

This is my Schema(userTb)

const userTbSchema = new Schema({
  _id: mongoose.Schema.Types.ObjectId,
  userId: String,
  folders: [
    {
      folderTitle: String,
    }
  ]
}

and this is the result of the query of my Schema(userTb).

{
    "_id": "5fc4c13f32ab3174acb08540",
    "userId": "go05111",
    "folders": [
        {
            "_id": "5fb7b0473fddab615456b166",
            "folderTitle": "first-go"
        },
        {
            "_id": "5fb7b0473fddab615456b16b",
            "folderTitle": "second-go"
        }
    ]
}

I want to get the only { "folderTitle" : "first-go" } folder's object, like...

{
    "_id": "5fb7b0473fddab615456b166",
    "folderTitle": "first-go"
}

so I query like this

router.get('/folder/:folderId', (req, res, next) => {
    UserTb.find({ folders : { "$elemMatch" : { _id : req.params.folderId} } })
    .exec()
    .then(docs => {
        res.status(200).json({
            docs
        }); 
    })
    .catch(err => {
        res.status(500).json({
            error: err
        });
    });
});

but the result is nothing changed.

I tried a few different ways, but it didn't work out.

how can I fix it in mongoose(don't use aggregate)?

would you please help me?

Upvotes: 0

Views: 461

Answers (1)

J.F.
J.F.

Reputation: 15177

Without aggregation, the only thing you can do is using $elemMatch into projection find like this:

db.collection.find({
  "folders.folderTitle": "first-go"
},
{
  "_id": 0,
  "folders": {
    "$elemMatch": {
      "folderTitle": "first-go"
    }
  }
})

Example here

The output is only the folder/s whose name match with first-go.

Note that you get all values because you are using $elemMatch into query. According to documentation find gets two parameters: Query and projection.

Query is to filter the elements you want to get, so if you do only something like:

db.collection.find({
  "folders._id": "5fb7b0473fddab615456b166"
})

It will return the entire object where this filter match. Example here.
Note that only the object where exists one folder object with the given _id is returned. But is not returned the object into the array, the returned is the entire object.

So, you need to set your query and after that the projection using $eleMatch.

You can use an empty object {} or a find to filter and get first the document anda later the specific array object.

So the query has to do something like:

db.collection.find(
{
  /* First find the documents whose match this filter.
     Here you will get the entire document, not only the 
     object into the array you want*/
},
{
 /* Second filter the documents and get the value you want.
    In this case folderTitle = first-go*/
})

And, that's true the output is not exactly what you want, this is the folders field only with values whose match the $elemMatch criteria. But using only find is the best approach I think.

Upvotes: 1

Related Questions