I have a cyclic dependency problem with two mongoose schemas which depend on each other. Code is as follows:
// user.model.js
var mongoose = require('mongoose');
var transactionSchema = mongoose.model('Transaction').schema;
var userSchema = mongoose.Schema ({
name : String,
wallet: Number,
transactions: [ {type: mongoose.Schema.Types.ObjectId, ref: 'Transaction'} ]
});
var User = mongoose.model('User', userSchema);
// transaction.model.js
var mongoose = require('mongoose');
var userSchema = mongoose.model('User').schema;
var transactionSchema = mongoose.Schema ({
sourceUser: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
targetUser: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
amount: Number,
status: String
});
var Transaction = mongoose.model('Transaction', transactionSchema);
Loaded as such:
// app.js
var mongoose = require('mongoose');
require('./models/user.model');
require('./models/transaction.model');
Issue is obvious but unclear how to solve.
user.model.js
var mongoose = require('mongoose');
var userSchema = mongoose.Schema ({
name : String,
wallet: Number,
transactions: [ {type: mongoose.Schema.Types.ObjectId, ref: 'Transaction'} ]
});
var User = mongoose.model('User', userSchema);
transaction.model.js
var mongoose = require('mongoose');
var transactionSchema = mongoose.Schema ({
sourceUser: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
targetUser: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
amount: Number,
status: String
});
var Transaction = mongoose.model('Transaction', transactionSchema);
Related
I am creating a website where you can take and upload tests.
So there are two kinds of users Company(upload test) and Candidate(take test).
Now when i create a token how do I refer to both the schema's (schema of company and schema of candidate)?
const mongoose = require("mongoose");
const { ObjectId } = mongoose.Schema.Types;
let tokenSchema = new mongoose.Schema({
userId: { type: ObjectId, ref: "<?>" }
});
module.exports = mongoose.model("Token", tokenSchema);
Let's sat this is how you export both candidate and company schema:
module.exports = mongoose.model("Candidate", candidateSchema)
module.exports = mongoose.model("Company", companySchema)
Your token schema should be like the following:
let tokenSchema = new mongoose.Schema(
candidateId: { type: ObjectId, ref: "Candidate" },
comoanyId:{ type: ObjectId, ref: "Company" },
);
I was googling for last two days but no success. I need to perform inner join in mongoose with two schema but not getting response my other collection.
My question is what am I missing in my code? Please help me with this.
I want to get result of class and subjects also.
exports.classSubjectList = async (req, res, next) => {
const obj = await ClassSubject.find().populate('classmodel').exec();
res.status(200).json({
success: true,
response: obj
});
};
//ClassSubjectModel
const mongoose = require('mongoose');
mongoose.Promise = global.Promise
const Schema = mongoose.Schema
const classModel = require('../class/classModel');
const subjectModel = require('../subject/subjectModel');
var classsubject = new Schema({
ClassId: String,
SubjectId : String,
IsShow: { type: Boolean, default : true},
classmodel: { type: mongoose.Schema.Types.ObjectId, ref: classModel },
subjectmodel: { type: mongoose.Schema.Types.ObjectId, ref: subjectModel },
});
//Class Model
const mongoose = require('mongoose');
mongoose.Promise = global.Promise
const Schema = mongoose.Schema
var classinfo = new Schema({
ClassName: String,
IsShow: { type: Boolean, default : true},
});
module.exports = mongoose.model('classinfo', classinfo);
//SUBJECT Model
const mongoose = require('mongoose');
mongoose.Promise = global.Promise
const Schema = mongoose.Schema
var subject = new Schema({
SubjectName: String,
IsShow: Boolean,
});
module.exports = mongoose.model('subject', subject);
result
[
{
"IsShow": true,
"_id": "5e1efc0f354849246c472cfe",
"SubjectId": "5e1da60bf52acb30b87e92c4",
"ClassId": "5e1ec13ed777bf28d01e2481",
"__v": 0
}]
You should define ref as the name of your schema & not the object reference
Do it like this
classmodel: { type: mongoose.Schema.Types.ObjectId, ref: 'classinfo' }
subjectmodel: { type: mongoose.Schema.Types.ObjectId, ref: 'subject' },
// here 'classinfo' & 'subject' are the names you defined your schema with
You should populate both if you want a proper inner join
const obj = await ClassSubject.find().populate('classmodel').populate('subject').exec();
You must store ids of class & reference in classmodel & subjectmodel
key of your document for this to work
Hope this helps
I want to insert records in mongodb using mongoose but i am getting error "cannot overwrite "story" model once compiled"
app.post('/getdata', (req, res, next) => {
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/mydb');
var Schema = mongoose.Schema;
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var personSchema = Schema({
_id: Schema.Types.ObjectId,
name: String,
age: Number,
stories: [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});
var storySchema = Schema({
author: { type: Schema.Types.ObjectId, ref: 'Person' },
title: String,
fans: [{ type: Schema.Types.ObjectId, ref: 'Person' }]
});
var Story = mongoose.model('Story', storySchema);
var Person = mongoose.model('Person', personSchema);
res.send("Om Success");
})
You are initializing mongoose and all the schema everytime someone hits /getdata post endpoint and as you have express app main process will not be terminated until you so that manually or any unhandled error occurs.
So currently in your program, this is the scenario:
First Request to /getdata
Your mongoose will be initialized and Story and Person models are registered with mongoose object and this is global so you can use it from anywhere and this is unique too(your error is here).
From second Request to /getdata
You already registered Story and Person models with mongodb://localhost:27017/mydb DB so as it needs unique model it will throw an error.
Solution
put your initialization code somewhere else where it will be called only once. You can consider structure something like this: https://github.com/ridhamtarpara/express-es8-rest-boilerplate/blob/master/src/api/services/user/user.model.js
or if you want to do this in the same file(not recommended for obvious reasons) do something like this
var express = require('express');
var mongoose = require('mongoose');
var app = express();
var Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost:27017/mydb');
var personSchema = Schema({
_id: Schema.Types.ObjectId,
name: String,
age: Number,
stories: [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});
var storySchema = Schema({
author: { type: Schema.Types.ObjectId, ref: 'Person' },
title: String,
fans: [{ type: Schema.Types.ObjectId, ref: 'Person' }]
});
var Story = mongoose.model('Story', storySchema);
var Person = mongoose.model('Person', personSchema);
app.post('/getdata', (req, res, next) =>
{
res.send("Om Success");
})
This is doctors.js model:
var mongoose = require('mongoose'), Schema = mongoose.Schema;
var Patient = require('./patient.js');
var doctorSchema = mongoose.Schema({
firstName: String,
lastName: String,
qualifications: String,
photo: Buffer,
_patients: [{ type: Schema.Types.ObjectId, ref: 'Patient' }]
});
var Doctor = mongoose.model('Doctor', doctorSchema);
module.exports = Doctor;
This is patients.js model:
var mongoose = require('mongoose');
var Doctor = require('./doctor.js');
var patientSchema = mongoose.Schema({
firstName: String,
lastName: String,
dob: String,
gender: String,
primaryDiagnosis: String,
duration: String,
_doctorIncharge: {type: Number, ref: 'Doctor'},
hospitalNumber: String,
photo: Buffer
});
var Patient = mongoose.model('Patient', patientSchema);
module.exports = Patient;
Is this the way to make a one to many relationship work?
I have the following mongoose models in my express app:
//dog.js
var mongoose = require("mongoose");
var dogSchema = (exports.dogSchema = mongoose.Schema({
name: { type: String, required: true },
}));
Then I import dog.js to my user.js
//user.js
var mongoose = require("mongoose");
var dog = require("./dog");
var userSchema = mongoose.Schema({
user: { type: String, required: true },
pass: { type: String, required: true },
dogs: [dog.dogSchema],
});
Now, from my routes I am creating a new user like this:
var user = require("../models/user");
var dog = require("../models/dog");
dog = new dog.Dog(dogData);
user = new user.User(data); //this will of course contain also dogData
user.save(next);
Is this the correct way to do this kind of operation? I have the feeling that I might be generating a circular dependency somehow, and anyway it does not look right to me. Any ideas on how to create sub-documents where the schema is from another model file?
You can create simultaneous references in two directions without creating circular problems. Create a reference from one document to the other using ref. From the docs:
http://mongoosejs.com/docs/populate.html
var mongoose = require('mongoose')
, Schema = mongoose.Schema
var personSchema = Schema({
_id : Number,
name : String,
age : Number,
stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});
var storySchema = Schema({
_creator : { type: Number, ref: 'Person' },
title : String,
fans : [{ type: Number, ref: 'Person' }]
});
var Story = mongoose.model('Story', storySchema);
var Person = mongoose.model('Person', personSchema);
Then you can then choose to load the sub document using populate
Story.find({ --your criteria-- })
.populate('_creator')
.exec(function (err, story) {../});
You can then store the 2 schemas in separate .js files and require them both