Home > Blockchain >  How to insert post method with mongoose having a reference in node.js
How to insert post method with mongoose having a reference in node.js

Time:02-16

I'm using mongoose and have two schema models and one of them "control" has a reference in the fist model which is "framework" model. With node.js I'm trying to create a post method and testing it in the postman which is not successful. Not sure if I'm approaching this the right way:

Framework Schema:

const FrameworkSchema = new Schema({
  name: {
    type: String,
    trim: true
  },
  slug: {
    type: String,
    slug: 'name',
    unique: true
  },
  image: {
    data: Buffer,
    contentType: String
  },
  description: {
    type: String,
    trim: true
  },
  isActive: {
    type: Boolean,
    default: true
  },
  control: 
    {
      type: Schema.Types.ObjectId,
      ref: 'Control'
    },
  updated: Date,
  created: {
    type: Date,
    default: Date.now
  }
});

My Control schema:

const ControlSchema = new Schema({
   _id: {
     type: Schema.ObjectId,
     auto: true
   },
  mControlNo: {
    type: String
  },
  sControlNo: {
    type: String
  },
  name: {
    type: String,
    trim: true
  },
    slug: {
    type: String,
    slug: 'name',
    unique: true
  },
  description: {
    type: String,
    trim: true
  },
  isApplicable: {
    type: Boolean,
    default: true
  },
  updated: Date,
  created: {
    type: Date,
    default: Date.now
  }
});

My router api:

router.post(
  '/add',
  auth,
  role.checkRole(role.ROLES.Admin),
  async (req, res) => {
    try {
       const name = req.body.name;
       const description = req.body.description;
       const isActive = req.body.isActive;
       const control = {
         mControlNo: req.body.control.mControlNo,
         sControlNo: req.body.control.sControlNo,
         name: req.body.control.name,
         description: req.body.control.description,
         isApplicable: req.body.control.isApplicable
       };

      const framework = new Framework({
        name,
        description,
        isActive,
        control
      });

      const frameworkDoc = await framework.save();

      res.status(200).json({
        success: true,
        message: `Framework has been added successfully!`,
        framework: frameworkDoc
      });
    } catch (error) {
      res.status(400).json({
        error
        // error: 'Your request could not be processed. Please try again.'
      });
    }
  }
);

My json document when I tested it in postman:

{
 "name": "NCA2",
 "description": "testdescription",
 "isActive": true,
 "control": 
    {
    "mControlNo": "1",
    "sControlNo": "2",
    "name": "controltest",
    "description": "controldescription",
    "isApplicable": true
    }
}

Response I'm getting:

{
    "error": {
        "errors": {
            "control": {
                "stringValue": "\"{\n  mControlNo: '1',\n  sControlNo: '2',\n  name: 'controltest',\n  description: 'controldescription',\n  isApplicable: true\n}\"",
                "kind": "ObjectId",
                "value": {
                    "mControlNo": "1",
                    "sControlNo": "2",
                    "name": "controltest",
                    "description": "controldescription",
                    "isApplicable": true
                },
                "path": "control",
                "reason": {}
            }
        },
        "_message": "Framework validation failed",
        "message": "Framework validation failed: control: Cast to ObjectId failed for value \"{\n  mControlNo: '1',\n  sControlNo: '2',\n  name: 'controltest',\n  description: 'controldescription',\n  isApplicable: true\n}\" at path \"control\""
    }
}

CodePudding user response:

The whole point of using a framework like mongoose is to write models and let the framework check for you if the body you're sending it is right or wrong. You don't have to assign each variable from your body to your model. You can simply write the following, which will save lines:

const framework = new Framework(req.body);

(Of course, granted that the body has been correctly parsed to JSON via body-parser or another parser).

Then, you check for description or name to be present:

if (!description || !name)

but none of them exist. req.body.description and req.body.name do exist, possibly framework.description and framework.name do as well, but description or name are undefined variables.

The rest of the code looks good, if the error persists, please print out the error in the catch clause as others have suggested in the comments.


Following the code added in the question and the comments the OP made, we now have more elements to answer.

You have a ValidationError coming from mongoose, meaning one of the field you entered is not right. You can also see that it's coming from the field control.

In your Framework schema, you declare a field control that looks like that:

control: 
    {
      type: Schema.Types.ObjectId,
      ref: 'Control'
    },

That means that Framework is taking an ObjectID for this field, and not an object like you send it here:

const framework = new Framework({
        name,
        description,
        isActive,
        control
      });

The error is explicit on its own: Mongoose tried to cast your control object to an ObjectID and of course, it fails.

You have 2 solutions:

  • Either you implement your Control schema directly in your Framework schema as an object field
  • Or you create a separate Schema object in your route, save it, and give the ID to control when creating the Framework object.

The second solution could look something like this:

const control = new Control(req.body.control);
const controlDoc = await control.save();
const framework = new Framework({...req.body, control: controlDoc._id});
const frameworkDoc = await framework.save();

The first could look something like this:

const FrameworkSchema = new Schema({
  // all your Framework schema
  control: 
    {
      mControlNo: { type: String },
      sControlNo: { type: String },
      name: { type: String, trim: true},
      // and so on....
    },
});
  • Related