Mongoose.model vs Connection.model vs Model.model - node.js

I am bit confused with usage of models in mongoosejs
Models can be created using mongoose in these ways
Using Mongoose
var mongoose = require('mongoose');
var Actor = mongoose.model('Actor', new Schema({ name: String }));
Using Connection
var mongoose = require('mongoose');
var db = mongoose.createConnection(..);
db.model('Venue', new Schema(..));
var Ticket = db.model('Ticket', new Schema(..));
var Venue = db.model('Venue');
Using existing Model instance
var doc = new Tank;
doc.model('User').findById(id, callback);
Now what is the difference between model returned by Mongoose.model , Connection.model and Model.model. and when to use what ,
what is the recommended way to create/fetch model ?

mongoose.model ties the defined model to the default connection that was created by calling mongoose.connect.
db.model ties the model to the connection that was created by calling var db = mongoose.createConnection.
doc.model looks up another model by name using the connection that doc's model is tied to.
All three can be sensibly used in the same program; which one to use just depends on the situation.

ok here is what I found
Important! If you opened a separate connection using
mongoose.createConnection() but attempt to access the model through
mongoose.model('ModelName') it will not work as expected since it is
not hooked up to an active db connection. In this case access your
model through the connection you created:
var conn = mongoose.createConnection('your connection string');
var MyModel = conn.model('ModelName', schema);
var m = new MyModel;
m.save() // works
vs
var conn = mongoose.createConnection('your connection string');
var MyModel = mongoose.model('ModelName', schema);
var m = new MyModel;
m.save() // does not work b/c the default connection object was never connected

mongoose.connect is for you connect to same database,although your database is balance or replicaSet
db.model is for multiple connections open to Mongo, each with different read/write settings

Related

Mongoose not querying

I just recently migrated my DB to Atlas. After mongoose.connect I successfully get the promise returned and am connected to my DB.
However, if I do User.find({}).then(users=>{res.json(users)}) I do not get any users returned (empty array) (This all worked prior to migrating)
User Schema
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
// Create Schema
const UserSchema = new Schema({
email: {
type: String
}
});
module.exports = User = mongoose.model(
"User",
UserSchema.plugin(require("mongoose-autopopulate"))
);
If I query using MongoShell directly
db.getCollection("users").find({})
I get the expected results. I am not really sure how I should isolate the issue on my local server side.
I double checked my connection string and that is correct.
I contact Atlas and even though I was connected successfully to my DB the connection string was incorrect.
Atlas will display the connection string to use, but in fact, it was not the correct one to use. The support team helped me resolve what is actually should be. I migrated from mLab and I was still needing to use the name of my mLab DB name.

Mongoose Multiple Database For A single Application

How can I access the schema of the other database in mongoose?
E.g, db1 has users list, db2 has another list. My application has all the models defined only for db1. but now I want to access the list of db2 in my application. How can I achieve that?
You can use useDb function on Connection type. It returns another connection. If you share the same Schema then your code might look like below:
var mongoose = require('mongoose');
mongoose.connect('mongodb://127.0.0.1:27017/test');
var schema = new Schema({
// ...
});
var db = mongoose.connection;
var Model1 = db.model('schema', schema, 'colName');
var db2 = db.useDb('test2');
var Model2 = db2.model('schema2', schema, 'colName');

Webstorm autocomplete not working with project files

I decided to try Webstorm, mainly for the autocomplete feature, but I've got an issue with it.
I require a .js file of my project(Which in this case is a driver to communicate with my Database) but the autocomplete is not working properly:
var db = require('../../config/database');
var Validator = {};
Validator.isAKnownUserId = function (user_id) {
var query = 'SELECT * FROM users WHERE id = ?';
db.
};
The databse.js file :
var cassandra = require('cassandra-driver');
// Client connecting to the keyspace used by the application
var client = new cassandra.Client ({
keyspace: keyspace,
contactPoints: ['127.0.0.1']
});
module.exports = client;
As you can see nothing special. But for example the "execute" function that is available with the cassandra.Client is not autocompletes in my validator.js file when it is in the database.js file.
Furthermore, if I replace
var db = require('../../config/database');
with
var db;
db = require('../../config/database');
or
var db = new require('../../config/database');
then the autocomplete is working correctly in my file.
Can someone help me figure out this behavior and how to get a proper autocomplete ?
Thanks in advance

How do I access methods attached to a Schema in mongoose

I am experiencing some confusion regarding calling a method that I have attached to a schema in a project that I am working on. I am essentially accessing a document from the database and trying to compare the hashed password I have stored to the password that was submitted by the user on login. When I go to try and compare the password though, the method that I attached to the methods object of the schema is nowhere to be found. It doesn't even throw an error for me telling me that there is no such method. This is where I am setting the method on the schema:
var Schema = mongoose.Schema;
var vendorSchema = new Schema({
//Schema properties
});
vendorSchema.pre('save', utils.hashPassword);
vendorSchema.methods.verifyPassword = utils.verifyPassword;
module.exports = mongoose.model('Vendor', vendorSchema);
The function I am using as the compare method is a utility function that I created called verifyPassword, which is held in a utility file. The code for that function is here:
verifyPassword: function (submittedPassword) {
var savedPassword = this.password;
return bcrypt.compareAsync(submittedPassword, savedPassword);
}
I try to verify the password like this:
var password = req.body.password;
_findVendor(query)
.then(function (vendor) {
return vendor.verifyPassword(password);
});
I have promisified mongoose with bluebird promises if that makes any difference. I have tried a lot of things, but can't find any answer as to why nothing is happening when I try to invoke this method that I thought I had attached the schema. Any help would be greatly appreciated.
/*VendorSchema.js*/
var Schema = mongoose.Schema;
var vendorSchema = new Schema({
//Schema properties
});
vendorSchema.methods.method1= function{
//Some function definition
};
vendorSchema.statics.method2 = function{
//Some function definition
};
module.exports = mongoose.model('Vendor', vendorSchema);
Lets say i would like to access VendorSchema inside other file:
/*anotherfile.js*/
var VendorSchema= require('../VendorSchema.js');
var Vendor = new VendorSchema();
As we defined method2 as static you can access method2 inside anotherfile.js by using schemareference object VendorSchema.
VendorSchema.method2
But method1 is not static you can access method1 inside anotherfile.js using only after creating object instance of schema.
Vendor.method1 /*Vendor is object instance of the schema*/

sharing db connection across entire app in mongoose

With the latest mongoose update, you can no longer user models the way I've been doing. I need to share the same db connection across my entire app.
https://github.com/LearnBoost/mongoose/issues/1249
Here is the old way which no longer works:
./models/user.js
var mongoose = require('mongoose'), cfg = require('../config')
, Schema = mongoose.Schema
, db = mongoose.createConnection(cfg.mongo.uri, cfg.mongo.db);
...
module.exports = db.model('Item', ItemSchema);
How can I re-use db connection as suggested in github issue above?
I'm using var User = require('./models/user'); in several different places in my code base.
Option 1: Use a shared object
My model code looks similar, but instead of repeatedly requiring the modules I just require them once when the application starts and then assign the results to a shared object. For example if you are using an express app you could just so something like app.locals.models.User = require('./models/user');. Then anything with access to the app can see your models without needing a require.
Option 2: Ensure a single modification in the exported function
You can define your user module like so:
var mongoose = require('mongoose');
var userSchema = new mongoose.Schema({name: String});
var User = null;
module.exports = function(db) {
if (db && User === null) {
User = db.model('User', userSchema);
}
return User;
};
When you start your application you simply need to: require('./models/user')(db). Subsequent requires by other modules in your application can drop the db paramater, as User will only be set once.

Resources