Reputation: 2081
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
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
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
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