Babr
Babr

Reputation: 2081

How to import one mongoose schema to another?

I'm making a node app to consume json API and I'd like to separate parts of User schema into separate files because there are many fields in Profile and separating files keeps things cleaner:

So basically instead of

const userSchema = new Schema({
    username: { type: String, required: true },
    password: { type: String, required: true }, 
    profile: { 
      gender: {
       type: String,
       required: true
       },
      age: {
        type: Number
      },
      //many more profile fields come here

    }
});

I do this:

models/Profile.js is:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const profileSchema = new Schema({
      gender: {
      type: String,
      required: true
      },
      age: {
        type: Number
      }
      //the rest of profile fields
});

module.exports = Profile = mongoose.model('profile', profileSchema);

And the models/User.js is:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Profile = require('./Profile');

const userSchema = new Schema({
    username: { type: String, required: true },
    password: { type: String, required: true }, 
    profile: {type: Schema.Types.ObjectId, ref: 'Profile'},
});

module.exports = mongoose.model('users', userSchema);

The data for User and Profile are posted in the same json post.

However when node tries to save the object I get this error:

(node:4176) UnhandledPromiseRejectionWarning: ValidationError: users validation failed: profile: Cast to ObjectID failed for value "{ gender: 'male'...

How can I fix this?

Upvotes: 9

Views: 22748

Answers (3)

parth
parth

Reputation: 674

Match Model

// models/Match.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const matchSchema = new Schema({
      gender: {
      type: String,
      required: true
      },
      age: {
        type: Number
      }
});
module.exports = Match = mongoose.model('match', matchSchema);

User Model

// models/User.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const userSchema = new Schema({
    username: { type: String, required: true },
    password: { type: String, required: true }, 
    match: {type: Schema.Types.ObjectId, ref: 'match'},
});

module.exports = User = mongoose.model('users', userSchema);

Then in your request add following code.

const User = require('../model/user');
const Match = require('../model/macth');

app.get('/test', (req, res) => {

    let newMatch = new Match({ gender: 'male'});
    newMatch.save().then(matchData => {
        console.log(matchData);
        let newUser = new User({ match: matchData._id, username: 'abc', password: '123456'});
        newUser.save().then(userData => {
            console.log(userData);
        })
        .catch(err => console.log(err));
    })
    .catch(err => console.log(err));

});

Now Log out your result.

Upvotes: 1

mhv
mhv

Reputation: 73

If you create your model like

module.exports = Match = mongoose.model('match', matchSchema);

then you have to ref to it with same name as first argument, so instead of ref: 'Match' should be ref: match.

Then if you want to create new document you should do it like

const mongoose = require("mongoose");
const Match = require("./Match");
const User = require("./User");
...
const m = await Match.create({
    gender: "male"
});

const u = await User.create({
  username: 'user',
  password: 'password',
  match: m
});

And if you query it later e.g

console.log(await User.find({}).populate("match"));

you should get something like

[ { _id: 5bf672dafa31b730d59cf1b4,
username: 'user',
password: 'password',
match: { _id: 5bf672dafa31b730d59cf1b3, gender: 'Male', __v: 0 },
__v: 0 } ]

I hope that helped

...

Edit

If you getting all the data from one JSON you still have to somehow pass ObjectId as a parameter for your User model. And it has to be existing Match to make possible to populate query later.

E.g

const user = req.body; // user data passed
const match = user.match;
const savedMatch = await Match.create(match);
user.match = savedMatch;
const savedUser = await User.create(user);

Upvotes: 0

muellerra
muellerra

Reputation: 64

You can define it like this:

/Match.js:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const matchSchema = new Schema({
      gender: {
      type: String,
      required: true
      },
      age: {
        type: Number
      }
});

export const mongooseMatch = mongoose.model('match', matchSchema);

/User.js:

import mongooseMatch from './Match.js';

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Match = require('./Match');

const userSchema = new Schema({
    username: { type: String, required: true },
    password: { type: String, required: true }, 
    match: {type: Schema.Types.ObjectId, ref: 'Match'},
});

export const matchUser = userSchema.discriminator('matchUser', mongooseMatch);

Upvotes: 1

Related Questions