Mongoose and Model Connections - node.js

I'm trying to get my head around how mongoose uses it's connection. At the moment I have:
// Datastore.js
var mongoose = require('mongoose'),
conn = mongoose.createConnection();
...
conn.open(host, database, port, options, callback); // Opens connection
// Model.js
var mongoose = require('mongoose');
var Schema = new mongoose.Schema({...})
module.exports = exports = mongoose.model('MyModel', Schema);
// Controller.js
var mongoose = require('mongoose');
var MyModel = mongoose.model('MyModel'); // Retrieves the model ok
MyModel.find({}, function(err, docs){
if(err){} //
console.log(docs); // Does not work
});
However this doesn't work... it only works if somehow I pass the connection across like so:
// Datastore.js
var mongoose = require('mongoose'),
conn = mongoose.createConnection();
...
conn.open(host, database, port, options, callback); //
mongoose.set('db', conn);
// Controller.js
var mongoose = require('mongoose'),
db = mongoose.get('db');
var MyModel = db.model('MyModel'); // Retrieve the model using the connection instance
MyModel.find({}, function(err, docs){
if(err){} //
console.log(docs); // Works
});
I think I'm approaching this in the wrong way... should the first approach work, and I'm doing something wrong?

It's easiest to just open the default connection pool that's shared by all your mongoose calls:
// Datastore.js
var mongoose = require('mongoose'),
db = mongoose.connect('localhost', 'dbname');
Then in all your other files access the pool using mongoose.model(...).

Looking at the docs it says:
var mongoose = require('mongoose');
var db = mongoose.createConnection('localhost', 'test');
Perhaps you need to put your connection details in for the create Connection
var mongoose = require('mongoose'),
conn = mongoose.createConnection('localhost', 'test');

Related

set database and collection using mongoose

How do I set my database and collection using mongoose ? I am trying to connect to a mongodb atlas database using mongoose. My database is called "test_db" and collection name is "users" where would I specify that information ?
This is my shema (data.js):
// /backend/data.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
// this will be our data base's data structure
const DataSchema = new Schema(
{
_id: Number,
name: String,
password: String
}
);
// export the new Schema so we could modify it using Node.js
module.exports = mongoose.model("users", DataSchema);
and this is server.js:
const mongoose = require('mongoose');
const express = require('express');
var cors = require('cors');
const bodyParser = require('body-parser');
const logger = require('morgan');
const Data = require('./data');
const API_PORT = 3001;
const app = express();
app.use(cors());
const router = express.Router();
// this is our MongoDB database
const dbRoute = 'mongodb+srv://<user>:<password>#cluster0-bmihj.mongodb.net/test?retryWrites=true&w=majority';
;
// connects our back end code with the database
const conn = mongoose.connect(dbRoute, { useNewUrlParser: true });
//let db = mongoose.connection;
const db = conn.db('test_db');
var MyModel = mongoose.model('Test', new Schema({ name: String }));
db.once('open', () => console.log('connected to the database'));
// checks if connection with the database is successful
db.on('error', console.error.bind(console, 'MongoDB connection error:'));
// this is our get method
// this method fetches all available data in our database
router.get('/getData', (req, res) => {
Data.find((err, data) => {
if (err) return res.json({ success: false, error: err });
return res.json({ success: true, data: data });
});
});
Through this line, you are connected to MongoDB:
const conn = mongoose.connect(dbRoute, { useNewUrlParser: true })
Consider:
dbRoute = mongodb://DB-username:DBpassword#ds245901.mlab.com:44422/Database-Name";
Here is your data information
DB-username = Your database user name
DBpassword = Your database password
Database-Name = Your database name (which database you want to use)
Therefore, no need to connect to your desired database like this:
const db = conn.db('test_db');

passing mongoose as an argument to a function

I'm developing a node module. I need to pass the mongoose to my module to get three things (mongoose.connection, mongoose.connection.db, mongoose.mongo) out of it.
index.js (myModule - the module I developed)
function myModule(mongoose) {
var db = mongoose.connection;
var gfs = gridfsLockingStream(mongoose.connection.db, mongoose.mongo);
this.someFunction = function() {//some code here}
}
module.exports = myModule;
db.js (A user must use myModule like this)
var mongoose = require('mongoose');
var myModule = require('myModule');
var dbUrl = 'mongodb://localhost:27017/gfsTestDB';
mongoose.connect(dbUrl);
var readyObj = new myModule(mongoose);
module.exports = readyObj; // so that the user can use this everywhere
Then the user can use readyObj to do his/her work.
My problem is that only mongoose.connection is available in myModule function and I get this error(gridfsLockingStreamn cause the error):
Error: missing db argument
new Grid(db, mongo)
I'm using :
"mongodb": "3.0.4",
"mongoose": "4.11.6",
"gridfs-locking-stream": "1.1.1",
"gridfs-stream": "1.1.1",
One solution (idea from #GrégoryNEUT) (but I think it's not the correct way):
index.js no changes
db.js using promise and mongoose event handler
var mongoose = require('mongoose');
var myModule = require('myModule');
var dbUrl = 'mongodb://localhost:27017/gfsTestDB';
mongoose.connect(dbUrl);
module.exports = new Promise(function (resolve, reject) {
mongoose.connection.on('connected', function () {
var readyObj = new myModule(mongoose);
resolve(readyObj);
});
});
photoRouter.js (one of the user's files - the user want to use readyObj)
var readyObj = require('./db').then(function (readyObj) {
// then the user uses readyObj
}
Can the code be improved?
Looking at the documentation of mongoose connect
You can use of Promises.
var mongoose = require('mongoose');
var myModule = require('myModule');
var dbUrl = 'mongodb://localhost:27017/gfsTestDB';
mongoose.connect(dbUrl)
.then(
// The connection is ready to use!
() => {
var readyObj = new myModule(mongoose);
// ...
},
// Handle the connection error
(err) => {
// ...
},
);
You can use of Callbacks
var mongoose = require('mongoose');
var myModule = require('myModule');
var dbUrl = 'mongodb://localhost:27017/gfsTestDB';
mongoose.connect(dbUrl, (err) => {
if (err) {
// Handle the error
// ...
return;
}
// We get successfully connected to the database
var readyObj = new myModule(mongoose);
// ...
});

Mongo models not responding

I'm working on a new app and trying to get mongo set up locally for storage. My api endpoints are getting hit but as soon as I try to actually call a db operation - find or save - it doesn't respond.
var express = require('express');
var router = express.Router();
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var Person = require('./data/person');
var dbConfig = require('./config');
//database: 'mongodb://localhost:27017/persondb'
var db = mongoose.createConnection(dbConfig.database);
db.on('error', function() {
console.info('Error: Could not connect to MongoDB. Did you forget to run `mongod`?');
});
if (~process.argv.indexOf('mode_dev')) {
global.mode_dev = true;
console.log('Server started in dev mode.');
}
// configure app to use bodyParser()
// this will let us get the data from a POST
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use('/api', router);
router.route('/persons')
.post(function(req, res) {
debugger;
var person = new Person(); // create a new instance of the Person model
person.name = req.body.name;
person.save(function(err) {
debugger;
if (err)
res.send(err);
res.json({ message: 'Person created!' });
});
})
.get(function(req, res) {
Person.find(function(err, persons) {
debugger;
if (err)
res.send(err);
res.json(persons);
});
});
Here's the schema:
data/item.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var personSchema = new Schema({
name: String,
});
module.exports = mongoose.model('Person', personSchema);
I am running mongod before getting my webserver started. As soon as I get to the .save or .find calls, no error is thrown but the callbacks are never hit.
I would connect like this:
mongoose.connect("mongodb://localhost/persondb");
var db = mongoose.connection;
maybe this will help it explains problems using mongoose.createConnection(
if you use createConnection, you need to always reference that connection variable if you include a registered model, otherwise if you use mongoose to load the model, it will never actually talk to your database.
The other solution is to simply use mongoose.connect instead of
mongoose.createConnection. Then you can just use
mongoose.model(‘MyModel’) to load the requested model without needing
to carry around that db connection variable.

foo.find(...).execFind is not a function - mongoose schema model

I have defined a custom type and I am trying to return all entries from mongo contained in the referenced collection:
Participant.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var participantSchema= new Schema({
email: String,
});
module.exports = mongoose.model('Participant', participantSchema, 'participants')
api.js
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Participant = require('../models/Participant');
router.get('/all', function(req, res) {
var participant = mongoose.model('Participant');
//var participant = new Participant();
console.log(participant);
participant.find().execFind(function (arr,data) {
res.send(data);
});
});
module.exports = router;
But due something fishy, my model does not extend (I assume the default prototype)
participant.find(...).execFind is not a function
TypeError: participant.find(...).execFind is not a function
at /Users/bogdan/private/appName/routes/api.js:13:24
Any help is highly appreciated...
Thanks
execFind was replaced with exec back in one of the 3.x releases of Mongoose.
So you must now call exec instead of execFind.

Mongoose multiple connections

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'
});

Resources