I'm beginning with Mongoose and I want to know how to do this type of configuration:
A recipe has different ingredients.
I have my two models:
Ingredient and Recipe:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var IngredientSchema = new Schema({
name: String
});
module.exports = mongoose.model('Ingredient', IngredientSchema);
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var RecipeSchema = new Schema({
name: String
});
module.exports = mongoose.model('Recipe', RecipeSchema);
Check Updated code below, in particular this part:
{type: Schema.Types.ObjectId, ref: 'Ingredient'}
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var IngredientSchema = new Schema({
name: String
});
module.exports = mongoose.model('Ingredient', IngredientSchema);
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var RecipeSchema = new Schema({
name: String,
ingredients:[
{type: Schema.Types.ObjectId, ref: 'Ingredient'}
]
});
module.exports = mongoose.model('Recipe', RecipeSchema);
To Save:
var r = new Recipe();
r.name = 'Blah';
r.ingredients.push('mongo id of ingredient');
r.save();
Related
I am building an app with express using mongoose as ORM for my MongoDB database.
I have 2 models located in separate files : User and Posts.
User.js model looks like
var mongoose = require('mongoose'),
moment = require('moment'),
Schema = mongoose.Schema,
UserSchema = new Schema({
created_at: {type: Date, default: moment()),
name: String
});
module.exports = mongoose.model('user', UserSchema);
and the Posts.js model
var mongoose = require('mongoose'),
moment = require('moment'),
Schema = mongoose.Schema,
PostSchema = new Schema({
created_at: {type: Date, default: moment()},
user: {type: Schema.Type.ObjectId, ref: 'User'}
});
I call them in controllers in separate files that looks like
var Post = require('../models/User'),
User = require('../models/Posts');
Post.find().populate('user').exec();
This population returns me a MissingSchema error that says :
MissingSchemaError: Schema for model 'Posts' hasn't been registerd.
The connection to the database is in the main file : app.js
var mongoose = require('mongoose');
mongoose.connect('mongodb://127.0.0.1/database');
Can anyone tell me what's wrong with my code?
Because your reference is for "User", I think you just have to declare your first model with correct Typpo
module.exports = mongoose.model('User', UserSchema);
instead of
module.exports = mongoose.model('user', UserSchema);
Hope it helps.
I have the following setup:
/models/index.js
var glob = require('glob');
var mongoose = require('mongoose');
var Promise = require('bluebird');
mongoose.Promise = Promise;
mongoose.connect('mongodb://localhost/firstDB', {
useMongoClient: true
});
var models = glob.sync(__dirname + '/*.js', {ignore: '**/index.js'});
models.forEach(function (model) {
require(model);
});
/models/movie.js
var mongoose = require('mongoose');
var movieSchema = new mongoose.Schema({
title: String
}, {timestamps: true});
mongoose.model('movie', movieSchema);
/app.js
require('./models');
...
var Movie = mongoose.model('movie');
...
I would like to access secondDB models from the same app.js file, how can I do that?
Update: The end setup should look something like that:
(not sure how to pass the connection to the model)
/models/index.js
var glob = require('glob');
var mongoose = require('mongoose');
var Promise = require('bluebird');
mongoose.Promise = Promise;
var firstConnection = mongoose.connect('mongodb://localhost/firstDB', {
useMongoClient: true
});
var secondConnection = mongoose.connect('mongodb://localhost/secondDB', {
useMongoClient: true
});
var firstModels = glob.sync(__dirname + '/*.js', {ignore: '**/index.js'});
firstModels.forEach(function (model) {
require(model);
});
var secondModels = glob.sync(__dirname + '/second/*.js');
secondModels.forEach(function (model) {
require(model);
});
/models/movie.js
var mongoose = require('mongoose');
var movieSchema = new mongoose.Schema({
title: String
}, {timestamps: true});
mongoose.model('movie', movieSchema);
/models/second/car.js
var mongoose = require('mongoose');
var carSchema = new mongoose.Schema({
color: String
}, {timestamps: true});
mongoose.model('car', carSchema);
/app.js
require('./models');
...
var Movie = mongoose.model('movie');
var Car = mongoose.model('car');
...
Try this, Thanks!
var mongoose = require('mongoose')
var connection1 = mongoose.createConnection('connectionstring1');
var connection2 = mongoose.createConnection('connectionstring2');
Check this URL - http://mongoosejs.com/docs/connections.html
and Go to Multiple Connection Section.
Edit :
connectionOne.js
var mongoose = require('mongoose'),
mongoURI = 'mongodb://user:password#localhost:27017/dbOne';
module.exports = connectionOne = mongoose.createConnection(mongoURI);
connectionOne.on('connected', function() {
console.log('Mongoose connected to connectionOne');
});
require('./events')
connectionTwo.js
var mongoose = require('mongoose'),
mongoURI = 'mongodb://user:password#localhost:27017/dbTwo';
module.exports = connectionTwo = mongoose.createConnection(mongoURI);
connectionTwo.on('connected', function() {
console.log('Mongoose connected to connectionTwo');
});
require('./events')
events.js
var mongoose = require('mongoose'),
connectionOne = require('./connectionOne');
var Event = new mongoose.Schema({
name: { type: String, required: true },
date: { type: Date, required: false }
});
var connectionTwo = require('./connectionTwo');
var newEvent = new mongoose.Schema({
name: { type: String, required: true },
organizer: { type: String, required: true }
});
module.exports = {
connectionOne.model('Event1', Event);
connectionTwo.model('Event2', newEvent);
}
For more explanation - handling-multiple-databases-and-connections-with-mongoose
Note - I didn't test it.
When I'm trying to populate , this error is coming:
" MissingSchemaError: Schema hasn't been registered for model "
My models:
/models/course.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var User = require('./user')
var courseSchema = Schema({
courseName:String,
price:Number,
type:String,
_offeredBy:{type:Schema.Types.ObjectId,ref:User}
});
module.exports = mongoose.model("Course",courseSchem
models/user.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var bcrypt = require('bcrypt-nodejs');
var findOrCreate = require('mongoose-findorcreate')
var Course = require('./course')
var userSchema = Schema({
email:{type:String},
password:{type:String},
courseOffered:[{type:Schema.Types.ObjectId,ref:Course}]
});
module.exports = mongoose.model('User',userSchema);
routes/index.js
var Course = require('../models/course');
var User = require('../models/user');
var express = require('express');
var router = express.Router();
router.get('/user/profile',isLoggedIn,function(req,res,next){
res.render('user/profile',{csrfToken:req.csrfToken(),message:""})
});
router.post('/user/profile',isLoggedIn,function(req,res,next){
var courseInfo = req.body;
var newCourse = new Course();
newCourse.courseName = courseInfo.coursename;
newCourse.price = courseInfo.price;
newCourse.type = courseInfo.type;
newCourse._offeredBy = req.user;
newCourse.save(function(err,result){
if(err){
res.redirect('/user/profile');
}
});
Course
.findOne({courseName:courseInfo.coursename})
.populate('_offeredBy')
.exec(function(err,course){
if(err){
res.redirect('/user/profile');
}
});
});
Course is getting saved in the database, but the error is coming due to pouplating. I'm not writing the app.js, mongodb connections are made in app.js file.
Your models are trying to load another model which itself then tries to load the other model.
In your schemas you should set the refs as strings like this:
var courseSchema = Schema({
courseName: String,
price: Number,
type: String,
_offeredBy: { type:Schema.Types.ObjectId, ref: 'User' }
});
var userSchema = Schema({
email: String,
password: String,
courseOffered: [{ type: Schema.Types.ObjectId, ref: 'Course' }]
});
You can then remove the lines to require the other model within each model file. They are both loaded in 'routes/index.js' before being used.
Note: newCouse.save() is asynchronous so you should do you Course.findOne().populate() inside the 'save' callback.
doing mongoose db in nodejs.
i got an error: "schema is not defined".
in my model i have 2 files for different schemas: user and product, they look smth like:
'use strict';
var mongoose = require('mongoose'),
bcrypt = require("bcryptjs");
var UsersSchema = new Schema({
name: String,
email: String,
telephone: Number,
createdAt: {type: Date, default: Date.now},
updatedAt: {type: Date, default: Date.now}
});
var userModel = mongoose.model('User', userSchema);
module.exports.userModel = userModel;
I have nothing in routes, and in app.js, I've got:
var users = mongoose.model('User', userSchema);
var products = mongoose.model('Product', productSchema);
Previously I tried:
var users = require('../models/userSchema');
var products= require('../models/productSchema');
any advise? thanks
To resolve the "schema is not defined" issue, import the Mongoose schema:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
For the exports, I would suggest the following. No reason to nest this additionally, when you're defining one model per file:
var userModel = mongoose.model('User', userSchema);
module.exports = userModel;
Then you can require the model in other files as shown in your post, e.g.:
var users = require('../models/userSchema');
You can get rid of requiring mongoose models in your code by putting them in app.
Add index.js file in the folder (let's say 'models') where user.js and product.js are placed:
var fs = require('fs');
var path = require('path');
module.exports = function(app) {
app.models = app.models || {};
fs.readdirSync(__dirname).forEach(function(file) {
if (file !== "index.js" && path.extname(file) === '.js'){
var model = require(path.join(__dirname,file))(app);
app.models[model.modelName] = model;
}
});
};
Change user.js (and similarly product.js) file to
'use strict';
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
bcrypt = require("bcryptjs");
module.exports = function(){
var UsersSchema = new Schema({
name: String,
email: String,
telephone: Number,
createdAt: {type: Date, default: Date.now},
updatedAt: {type: Date, default: Date.now}
});
return mongoose.model("User", UsersSchema); //the name "User" here will be stored as key in app.models and its value will be the model itself
};
And in app.js insert a line
require("./app/models")(app) //pass app to the index.js, which will add models to it
Now you can use app.models.User and app.models.Product across the application.
Currently I have this code for my connection mongoose.js:
var mongoose = require('mongoose');
var uriUtil = require('mongodb-uri');
var mongodbUri = 'mongodb://localhost/db_name';
var mongooseUri = uriUtil.formatMongoose(mongodbUri);
mongoose.connect(mongooseUri);
module.exports = mongoose;
File that requires the connection is test.js:
var mongoose = require('../model/mongoose');
var schema = mongoose.Schema({...});
How can I update mongoose.js to use multiple connections with mongoose.createConnection(...) function?
I start with changes only for one connection when I do changes like that:
var mongoose = require('mongoose');
mongoose.createConnection('mongodb://localhost/db_name');
mongoose.open('localhost');
module.exports = mongoose;
I get "undefined is not a function".
If I use this code:
var mongoose = require('mongoose');
db = mongoose.createConnection('mongodb://localhost/db_name');
db.open('localhost');
module.exports = mongoose;
I get "Error: Trying to open unclosed connection"
Any advice?
Mongoose handling connections via connections pool
http://mongoosejs.com/docs/connections.html
You can use server: {poolSize: 5} option for increase/decrease pool (number of parallel connections)
If you need connections to different databases look here
Mongoose and multiple database in single node.js project
Example of multiple connections:
var mongoose = require('mongoose')
var conn = mongoose.createConnection('mongodb://localhost/db1');
var conn2 = mongoose.createConnection('mongodb://localhost/db2');
var Schema = new mongoose.Schema({})
var model1 = conn.model('User', Schema);
var model2 = conn2.model('Item', Schema);
model1.find({}, function() {
console.log("this will print out last");
});
model2.find({}, function() {
console.log("this will print out first");
});
OK. With your example I found a solution that fit my needs.
mongoose.js
var mongoose = require('mongoose');
mongoose.main_conn = mongoose.createConnection('mongodb://localhost/main');
mongoose.admin_conn = mongoose.createConnection('mongodb://localhost/admin');
module.exports = mongoose;
content.js
var mongoose = require('../model/mongoose');
var schema = mongoose.Schema({...});
/// functions here
schema.statics.func_a(){...};
schema.statics.func_b(){...};
// And finaly updated only one line
//exports.Content = mongoose.model('Content', schema);
exports.Content = mongoose.main_conn.model('Content', schema);
The only thing, is it OK to add connection objects to mongoose object or may be there is more elegant solution.
config.js
module.exports = {
default: 'main',
main: 'mongodb://localhost/main',
admin: 'mongodb://localhost/admin',
};
connection.js
const mongoose = require('mongoose');
const config = require('./config');
mongoose.Promise = global.Promise;
function createConnection(name) {
return mongoose.createConnection(config[name]);
}
module.exports = createConnection(config[config.default]);
module.exports.on = createConnection;
model.js (custom class)
const connection = require('./connection');
class Model {
constructor(name, data) {
this.data = data;
return this.connection().model(name, data.schema);
}
connection() {
if (this.data.connection) {
return connection.on(this.data.connection);
}
return connection;
}
}
module.exports = Model;
user.js
const Schema = require('mongoose').Schema;
const conn = require('./connection');
const Model = require('./model');
const userSchema = new Schema({
name: String,
email: String,
password: String
});
// USING MONGOOSE MODEL
// default connection
const UserM1 = conn.model('User', userSchema);
// admin connection
const UserM2 = conn.on('admin').model('User', userSchema);
// USING CUSTOM MODEL
// default connection
const UserC1 = new Model('User', {
schema: userSchema
});
// admin connection
const UserC2 = new Model('User', {
schema: userSchema,
connection: 'admin'
});