Mongoose Sub-documents on separate files, how to embed them - node.js

I'm defining my application models and i have separate files for each model that i'm defining, my question is, i need to create a model that use a sub-document, but that's on another file, how can i use that Schema on my model ? what i mean is that all examples i've seen declare the Child model and the Parent on the same file, example:
var childSchema = new Schema({ name: 'string' });
var parentSchema = new Schema({
children: [childSchema]
});
I have one file called user.js that defines the user model :
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var userSchema = new Schema({
_id : Schema.Types.ObjectId,
username : String,
});
module.exports = mongoose.model( 'User', userSchema );
And on another file called sport.js i have the other model definition for the sports:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var sportSchema = new Schema({
_id : Schema.Types.ObjectId,
name : String
});
module.exports = mongoose.model( 'Sport', sportSchema );
So on my user model I need to define a field for the sports that the user will follow, but i do not know how to define that sub-document since the sports definition is on another file, I tried this:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var SportsModel = require('sport');
var userSchema = new Schema({
_id : Schema.Types.ObjectId,
username : String,
sports : [SportsModel]
});
module.exports = mongoose.model( 'User', userSchema );
But i'm not sure if that's the correct way since what i'm exporting is the model, not the Schema.
Thanks in advance, i want to define each model on separate files to maintain order.

You can access a Model's schema via its schema property. So this should work:
var userSchema = new Schema({
_id : Schema.Types.ObjectId,
username : String,
sports : [SportsModel.schema]
});

Use ref
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var userSchema = new Schema({
_id : Schema.Types.ObjectId,
username: String,
sports : [{ type: Schema.Types.ObjectId, ref: 'Sport' }]
});
module.exports = mongoose.model('User', userSchema);
Incidentally, with ref, you can use .populate('sports') when you query, and mongoose will expand those types for you.

Related

Relationship between two schemas in mongodb using mongoose

I have two schemas first one is countrySchema which has country id and name:
Below is the schema code:
var countrySchema = new Schema({
country_id:String,
country_name:String
});
var countryArray = mongoose.model('countryArray',countrySchema);
Another schema is stateSchema which has state id and state name:
below is the schema code:
var Schema = mongoose.Schema;
var stateSchema = new Schema({
state_id:String,
state_name:String,
});
var states = mongoose.model('states',stateSchema);
Now, in stateSchema i want to have state_id, country_id which is actually coming from the countrySchema and the state_name. How do I do this ?
You can add the country_id as follows and refer the country module in your state module with ObjectId of the country. Then you have to use the objectId which created by mongoose for the particular country as the country_id of stateSchema.
countrySchema
var countrySchema = new Schema({
_id:Schema.Types.ObjectId,
country_id:String,
country_name:String
});
var countryArray = mongoose.model('countryArray',countrySchema);
stateSchema
var stateSchema = new Schema({
_id:Schema.Types.ObjectId,
state_id:String,
country_id: {Schema.Types.ObjectId, ref:'countryArray'},
state_name:String,
});
Try This One..
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var countrySchema = new Schema({
country_id:String,
country_name:String
});
var countryArray = mongoose.model('countryArray',countrySchema);
var stateSchema = new Schema({
state_id:String,
state_name:String,
country: { type: Schema.Types.ObjectId, ref: 'countryArray' },
});
var states = mongoose.model('states',stateSchema);

Aggregation and populate using mongoose

I have two collection like this:
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var GradeSchema = new Schema({
gID: { type: Number, ref: 'User'},
grade: Number,
created_at: Date,
updated_at: Date,
type: Number
});
var Grade = mongoose.model('Grade', GradeSchema);
module.exports=Grade;
and:
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var UserSchema = new Schema({
name: String,
lastName:String,
uID: { type: Number,ref:'Grade' },
phone: String
});
var User = mongoose.model('User', UserSchema);
module.exports=User;
how can i first aggregate and then populate to have both collection information??
i used this command using $lookup in mongodb and it return my suggested documents:
db.grades.aggregate([{$lookup
{from:"users",localField:"gID",foreignField:"uID",as: "result"}},{$match:
{"type":0}},{"$sort":{"grade":-1}}])
but when i used this in mongoose the "result" is [] and connection to user collection is failed:
Grade.aggregate([{"$lookup":
{"from":"User","localField":"gID","foreignField":"uID","as": "result"}},
{"$match":{"type":3}},{"$sort":{"grade":-1}}]).exec(function(err, data)
{console.log(data);});

MissingSchemaError: Schema hasn't been registered for model when crossed references

I'm using mongoose and I'm trying to do this:
user.model.js
var mongoose = require('../../db/mongodb.connector'),
Schema = mongoose.Schema;
require('./offer.model');
var Offer = mongoose.model('Offer');
var userSchema = new Schema({
name: { type: String },
myOffers: [{type: Schema.Types.ObjectId,ref: 'Offer'}],
});
module.exports = mongoose.model('User', userSchema);
offer.model.js
var mongoose = require('../../db/mongodb.connector'),
Schema = mongoose.Schema;
require('./user.model');
var User = mongoose.model('User');
var commentSchema = new Schema({
user: {type: Schema.Types.ObjectId,ref: 'User'},
comment: {type: String},
likes: {type: Number}
});
var offerSchema = new Schema({
name: {type: String},
comments: [commentSchema],
likes: {type:Number}
});
module.exports = mongoose.model('Offer', offerSchema);
My problem is when I execute the server it returns :
D:\WebStorm\Alertame-Backend\node_modules\mongoose\lib\index.js:362
throw new mongoose.Error.MissingSchemaError(name);
^
MissingSchemaError: Schema hasn't been registered for model "User".
Use mongoose.model(name, schema)
at Mongoose.model (D:\WebStorm\myproject\node_modules\mongoose\lib\index.js:362:13)
at Object.<anonymous> (D:\WebStorm\myproject\db\models\offer.model.js:9:21)
.......
If I remove the inports in offer.model the server start normally
require('./user.model');
var User = mongoose.model('User');
EDIT TO EXPLANATION:
Offers are a individual entity and it would be assigned or not to an existing user (user has an array of assigned offer refs). On the other hand offers have an array of comment refs wich be writed by existing users.
What would I'm doing wrong?
You are trying to include offer.model from user.model and user.model from offer.model. Each file tries to include itself.
That is the reason it gives an error of undefined schema!

Find all documents which have certain element is not undefined with Mongoose

This is a Event model:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var Event = new Schema({
eventname: String,
location: String,
note: String,
remind: String,
userid: mongoose.Schema.Types.ObjectId,
projectid: mongoose.Schema.Types.ObjectId,
});
module.exports = mongoose.model('Event', Event);
If event belongs to a project it will save the id of project in projectid, if not projectid will be undefined.
I wonder how to find all the documents which have projectid is not undefined with mongoose?
You can use Query#exists for that:
Event.where('projectid').exists().exec(function(err, docs) {
...
});

is it possible to reference a subdocument schema in mongoose?

is it possible to reference a sub document schema in mongoose ?
just like below
var sectionSchema = mongoose.Schema(
{
id:{type:String,required:true},
name:{type:String,required:true}
});
var courseSchema = mongoose.Schema(
{
id:{type:String,required:true},
name:{type:String,required:true},
sections:[sectionSchema]
});
var studentSchema = mongoose.Schema(
{
id:{type:String,required:true},
name:{type:String,required:true},
course:{type:mongoose.Schema.Types.ObjectId,ref: 'courseSchema'},
section:{type:mongoose.Schema.Types.ObjectId,ref: 'sectionSchema'},
contactnumber:{type:String,required:true},
parentname:{type:String,required:true}
});
var schoolSchema = mongoose.Schema(
{
id:{type:String,required:true},
name:{type:String,required:true,unique:true},
address:{type:String,required:true},
year:{type:String,required:true},
contactnumber:{type:String,required:true},
courses:[courseSchema],
students:[studentSchema]
});
var School = mongoose.model('School',schoolSchema);
in the above model i have section inside course which is inside school document.
i have students schema which is inside school document i want course to point to course schema and section to point to section schema.so is it possible to refer a sub document schema in mongoose.

Resources