I am currently unsuccessfully trying to persist document to mongodb using nodejs and mongoosejs.
This my code structure:
The start.js simply initializes my app and creates mongod connection detailed in mongodb.js. The connection is succesfully established and can be seen in mongodb console.
this my model.js
var mongoose = require('mongoose');
var regSceham = new mongoose.Schema({
userId: String,
name:String,
mob:String,
email:String
})
var RegistrationModel = mongoose.model('registration', regSceham);
exports.RegistrationModel = RegistrationModel;
this is my datalayer.js:
var mongoose = require('mongoose');
var mongodb = require('./mongodb');
var model = require('./model');
//var RegistrationModel = mongoose.model('RegistrationModel');
/////////////////////////////////
function save(data){
console.log('inside save >>>>> ' + data);
var regModel = new model.RegistrationModel(data);
console.log('after model');
regModel.save(function(err,regModel){
console.log('inside mongoose save');
if(err)
console.log(err);
});
}
require('./model')
exports.save = save;
when I call the save method in datalayer.js the "inside save >>>>> " statement logged to console and then nothing happens. It seems the var regModel = new model.RegistrationModel(data); statement fails without any error and I donot have any clue why. Any suggestion would be highly appreciated.
sample post data as requested :
{
"userId":"tesrwetId",
"name":"Test",
"mob":"2536245632",
"email":"ashdjas#sa.com"
}
Update 24/06
I am starting to think that since the connection to mongoose is established after my model initialization this problem is experienced. I am unable to get the connection to happen before model is initialized.
Below is the file initialisation sequence. Though the mongodb.js(the mongoose connection) is initilaized first, the on connect method gets called after model.js is initialized.
The mongodb.js file:
console.log('mongodb....');
var mongoose = require('mongoose');
var configure = require('./configure');
// create database
//console.log('sadasdasdsa >>>>>>>' + configure.creds.mongodb)
mongoose.connect(configure.creds.mongodb);
mongoose.connection.on('connected', function () {
console.log('MOngodb connection open to ' + configure.creds.mongodb);
require('./model');
});
// If the connection throws an error
mongoose.connection.on('error',function (err) {
console.log('MOngodb connection error: ' + err);
});
// When the connection is disconnected
mongoose.connection.on('disconnected', function () {
console.log('MOngodb connection disconnected');
});
process.on('SIGINT', function() {
mongoose.connection.close(function () {
console.log('MOngodb connection disconnected through app termination');
process.exit(0);
});
});
require('./model');
update 28/06
I have since realised this understanding regarding loading sequence is incorrect. read here
Might have something to do with you're connection using the mongodb library and then trying to save using mongoose. Mongoose has mongodb as a dependency and is probably not resolving to the connection you've made. Remove your mongodb code and use the mongoose connect() function to establish db connection.
something like:
mongoose.connect('mongodb://localhost:port/test', function(err){
if(err) console.log(err);
else console.log('Connected');
});
Related
This is the error I am getting . please help to resolve this
Code
const MongoClient = require('mongodb').MongoClient;
const uri = "mongodb+srv://userName:password#saichaitanyacluster-1m22k.mongodb.net/test?retryWrites=true&w=majority";
const client = new MongoClient(uri, { useNewUrlParser: true });
client.connect(err => {
const collection = client.db("test").collection("devices");
client.close();
});
You should add a check to confirm that there is no error in connection before calling client.db(). The connection code should be something like this:
// ...Everything that was here before
client.connect(err => {
if (err) {
console.log("There was an error connecting to the database");
// Any other logic that you want to use to handle the error should live here.
// Add a return statement to help avoid executing
// the code below that relies on a successful connection
return;
}
const collection = client.db("test").collection("devices");
client.close();
});
I hope this helps.
I was getting an error like this in Node:
TypeError: Argument must be a string
at TypeError (native)
at Buffer.write (buffer.js:791:21)
at serializeObjectId
<snip>
the conditions were some uses of ObjectID's when doing a find operation with MongoDB. Some uses of ObjectID's raised this error and some did not. The only thing that mattered was where the ObjectID came from. If it was pulled from an existing collection, it worked. If I generated it myself (e.g., using ObjectID.createFromHexString), it failed as above.
Change mongodb version to 2.1.6.
I spent several hours tracking this one down. The problem came down to my use of Mongoose. I was using Mongoose schemas for some of my Collections and not using Mongoose for others. Here's the file containing my problematic code:
// Some common MongoDb operations and data.
'use strict';
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var logger = require('./Logger');
var mongoose = require('mongoose');
// TODO: Take this out for production.
mongoose.set('debug, true');
var PSSharingInvitations = require('./PSSharingInvitations')
var connectedDb = null;
// Call this just once, at the start of the server.
// TODO: Need better error handling when can't initially connect. Right now have an ugly looking error when Mongo is not already started and we try to start our server.
exports.connect = function(mongoDbURL) {
MongoClient.connect(mongoDbURL, function(err, db) {
assert.equal(null, err);
if (!db) {
logger.error("**** ERROR ****: Cannot connect to MongoDb database!");
}
else {
mongoose.connect(mongoDbURL);
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
// SCHEMA's
exports.SharingInvitation = PSSharingInvitations.buildSchema(mongoose);
logger.info("Mongoose: Connected to MongoDb database");
});
connectedDb = db;
logger.info("Mongo: Connected to MongoDb database");
}
});
};
exports.db = function () {
return connectedDb;
};
// Call this just once, when the server shuts down.
exports.disconnect = function() {
};
The problem turned out to be the line:
connectedDb = db;
Where db was the mongoose.connection. That is, I was using the mongoose.connection as my db for MongoDB Collections that were not using Mongoose. This caused intermittent errors.
The revised (and so far working!) code is as follows:
exports.connect = function(mongoDbURL) {
MongoClient.connect(mongoDbURL, function(err, db) {
assert.equal(null, err);
if (!db) {
logger.error("**** ERROR ****: Cannot connect to MongoDb database!");
}
else {
connectedDb = db;
logger.info("Mongo: Connected to MongoDb database");
mongoose.connect(mongoDbURL);
var connectedMongooseDb = mongoose.connection;
connectedMongooseDb.on('error', console.error.bind(console, 'connection error:'));
connectedMongooseDb.once('open', function() {
// SCHEMA's
exports.SharingInvitation = PSSharingInvitations.buildSchema(mongoose);
logger.info("Mongoose: Connected to MongoDb database");
});
}
});
};
I am trying to test my db connection with jasmine.
MongoClient is an object and is defined. However err returns undefined, naturally my test fails. Does Mongoose simply return undefined if there is no error?
Is there another way to check for the connection?
describe("MongoDB", function() {
it("is there a server running", function(next) {
var MongoClient = require('mongoose');
MongoClient.connect('mongodb://127.0.0.1:27017/panther_dev', function(err) {
expect(err).toBe(null);
next()
});
});
});
Thank you
Another way to check your connection is to use Connection#readyState. It returns one of four values which are:
0 = disconnected
1 = connected
2 = connecting
3 = disconnecting
So in your example, to test for a connection, it would look something like:
it("is there a server running", function(next) {
var MongoClient = require('mongoose');
MongoClient.connect('mongodb://127.0.0.1:27017/panther_dev', function(err) {
expect(MongoClient.readyState).toBe(1);
next();
});
});
When I am trying to run the mocha test i am getting "Cannot determine state of server"
since the mongoose connection is in connecting state.
Please suggest how to handle this scenario.
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
console.log('conn ready: '+mongoose.connection.readyState);
// "conn ready: 2" i.e connecting for test case as well as from user register form
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId,
UserSchema = new Schema({
// schemas
});
UserSchema.statics.newUser = function (uname, email, pass) {
var instance = new User();
instance.uname = uname;
instance.email = email;
instance.pass = pass;
console.log("conn state: "+mongoose.connection.readyState);
// "conn state: 2" i.e connecting for test case. But 1 i.e connected for user register form
instance.save(function (err) {
// Do rest
});
};
var User = mongoose.model('User', UserSchema);
exports.User = User;
DB connections happens asynchronously so when you check up on it straight after calling connect it's likely going to report that it's still connecting. If you want to do something after connection, you need to pass in a callback
mongoose.connect('mongodb://localhost/test', function (error) {
// Do things once connected
});
As for how to handle it in your scenario, my suggestion is to separate connection from your models and connect to MongoDB when required
So if you're testing your user model in mocha, this could be done in the Before hook
var mongoose = require("mongoose");
// Load in your user model wherever that is
var User = require("../models/user");
describe("My user model tests", function () {
// Connect to mongodb here before you start testing
before(function (done) {
mongoose.connect('mongodb://localhost/test', function (error) {
if (error) throw error; // Handle failed connection
console.log('conn ready: '+mongoose.connection.readyState);
done();
});
});
// And include disconnect afterwards
after(function (done) {
mongoose.disconnect(done);
});
// Test your user model down here
it("passes some tests");
});
Depending on how you've structured your app, I'd suggest you move DB connection to a sensible location (e.g. server configuration). When you test your entire app (e.g. integration testing), you would start your server in the Before hook
In addition, if you have your mongoose connection routines in another file (like me), during the asynchronous nature of JS, you should wait a little for the readyState to be 'connected' (1). I solved it in 'before':
var app = require('../server'); //I have mongoose connection in this file
var mongoose = require('mongoose');
var context = describe;
describe('Initial DB routines', function() {
before(function (done) {
mongoose.connection.on('connected', done);
});
it('Should connect to MongoDB', function(done) {
mongoose.connection.readyState === 1 ? done(): done(false);
});
});
Hi is there a way to switch database with mongoose?
I thought I could do it like that:
mongoose.disconnect();
mongoose.connect('localhost',db);
but it does not work I receive this error:
Error: Trying to open unclosed connection.
I do not know if it is because is asynchronous
As already stated you could do it using useDb function :
Example code :
async function myDbConnection() {
const url = 'mongodb+srv://username:password#cluster0-pauvx.mongodb.net/test?retryWrites=true&w=majority';
try {
await mongoose.connect(url, { useNewUrlParser: true });
console.log('Connected Successfully')
// Here from above url you've already got connected to test DB,
So let's make a switch as needed.
mongoose.connection.useDb('myDB'); // Switching happens here..
/**
* Do some DB transaction with mongoose models as by now models has already been registered to created DB connection
*/
} catch (error) {
console.log('Error connecting to DB ::', error);
}
}
Or if you wanted to create a complete new connection then you've to try mongoose.createConnection(). Just for reference in case of mongoDB driver you would use ::
mongodb.MongoClient.connect(mongourl, function(err, primaryDB) {
// open another database over the same connection
const secondaryDB = primaryDB.db(SECONDARY_DATABASE_NAME);
// now you can use both `database` and `database2`
...
});
Ref : mongoose multiple different connections, mongoose useDb(), mongoDB driver switch connections
It is asynchronous. If you pass a callback function to disconnect and try to connect to the next database in that callback, it will work.
Ex.
var mongoose = require('mongoose')
mongoose.connect('mongodb://localhost/test1', function() {
console.log('Connected to test 1')
mongoose.disconnect(connectToTest2)
})
function connectToTest2() {
mongoose.connect('mongodb://localhost/test2', function() {
console.log('Connected to test 2')
process.exit()
})
}
The top-voted answer had thrown me in a loop for a few hours. To help the OP and others who may have the same issue, here's my take on the solution:
Suppose you have two databases with the same schema and you want to switch between them on the fly. Let's call them DB1 and DB2. Here's how you can go about doing that:
(async () => {
const connection = await mongoose.createConnection(url, options);
const getModel = (database) => {
const dbConnection = connection.useDb(database);
return dbConnection.model('Model', modelSchema);
};
const Db1Model = getModel('DB1');
const Db2Model = getModel('DB2');
})();
Tested on Node.js v12 and Mongoose v5.
One way you can achieve this is by appending the database name with the database URL. For eg: if you are working with localhost
mongoose.connect('mongodb://localhost:portNumber/xyz_db');
When you connect like this, all your models will be saved in the xyz_db under your model as a collection.
You should use the useDb function like so:
mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true
});
mongoose.connection.useDb('Users'); # Change the string to the name of the database you want to use