Christian Vazquez
Christian Vazquez

Reputation: 66

get by id in mongoose

If I want to get by id a only subdocument that is an array into a document, how I need to call it? I have these models

/* Build */
var buildSchema = new Schema({
  buildName: String,
  package: [packageSchema],
  postedBy: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'user'
  }
})
var Build = mongoose.model('build', buildSchema)

/* Project */
var projectSchema = new Schema({
  projectName: String,
  build: [buildSchema],
  postedBy: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'user'
  }
})
var Project = mongoose.model('project', projectSchema)

my get function and route is this:

router.get('/build/:id', function (req, res, next) {
  var token = helperJwt.decodeToken(req)
  jwt.verify(token, helperJwt.secret, function (error, decoded) {
    if (error) {
      res.status(401)
    } else {
      Project.findOne({ _id: req.params.id}, 'build', function (err, build) {
        if (err) {
          res.status(401)
        } else {
          build.findOne({build: build._id}, 'postedBy', 'email', function (err, getBuild) {
            if (err) {
              res.status(401)
            } else {
              return status(200).json(build)
            }
          })
        }
      })
    }
  })
})

that is good or how can I do for get only one build?

I'm using vue as front end but it doesn't recognise only one build data.

I don't know how to findById a subdocument.

I want to bring something like:

{
    "_id" : ObjectId("5a26fbfd1866893baf14b175"),
    "postedBy" : "5a2021539f1d222bfc915fa2",
    "projectName" : "El pipiripau",
    "build" : [ 
        {
            "buildName" : "bdfbdgf",
            "postedBy" : ObjectId("5a2021539f1d222bfc915fa2"),
            "_id" : ObjectId("5a26fc0dbe4de0039cdae0c7"),
            "package" : []
        }, 
}

Upvotes: 0

Views: 2567

Answers (2)

moldypenguins
moldypenguins

Reputation: 509

https://mongoosejs.com/docs/api.html#model_Model.findById

// Find the adventure with the given `id`, or `null` if not found
await Adventure.findById(id).exec();

// using callback
Adventure.findById(id, function (err, adventure) {});

// select only the adventures name and length
await Adventure.findById(id, 'name length').exec();

Upvotes: 0

Steve Holgado
Steve Holgado

Reputation: 12089

If you use buildSchema inside of projectSchema, the build array will contain subdocuments so they won’t have ids.

You could set a custom id field in your build schema and then reference that in your query, but you would have to take care of setting those ids when you save your project docs.

Alternatively, if your build docs are being stored in a separate collection (as you have a build model) then they will have an _id field and you could store an array of references to the build model in your projectSchema:

var projectSchema = new Schema({
  projectName: String,
  build: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'build'
  }],
  postedBy: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'user'
  }
})

And then, assuming req.params.id is the id of a build doc, you could find projects where the build array has the id and then use populate to replace the array of build ids with the corresponding subdocuments:

Project
  .find({ build: req.params.id })
  .populate('build')
  .exec(function (err, projects) {
    if (err) {
      // Handle error
    } else {
      // For each project, filter builds for just the one matching the id param
      projects.forEach(project => {
        project.build = project.build.filter(item => item._id == req.params.id )
      })
      // Handle result
    }
  })

Here are the docs on population: http://mongoosejs.com/docs/populate.html

I hope this helps.

Upvotes: 1

Related Questions