How should mongoose's model.on('index', ...) be used? - node.js

In looking at the documentation for MongooseJS for MongoDB/Node.js, it appears that indexing may be specified on an object like so:
var MyModelSchema = new Schema({ name: String, index: true });
var MyModel = mongoose.model('MyModel', MyModelSchema);
MyModel.on('index', function()
{
doStuff();
});
Per the documentation, Mongoose will call ensureIndex() upon startup unless the "autoIndex" option is explicitly set to false on the schema. Once this is completed, the 'index' event will be emitted on the model, which would trigger the callback.
My understanding is that this allows a user of a model to ensure that all indexing has been completed prior to use of a model.
I believe I heard mention of doing this via app.configure, although I'm not sure how this could be done. Maybe there is another way to guarantee completion of this indexing operation prior to other parts of the application relying on the exported model?
How should this properly be used?

The 'index' event on your model is there to alert you to any errors that occurred in the model's ensureIndex calls. You don't need to delay use of the model until the event fires. That would get pretty messy.

I found it useful to add the following to the area used to configure the project's mongoose settings.
let mongoose = require('mongoose');
mongoose.Model.on('index', function(err) {
if (err) logger.error(err);
});

Related

Where data will be stored in Mongo DB by default, when we use mongoose with Express

I am new to Node JS technology. I have 3 basic doubts.
In my nodeJS application, I connected to mongodb using mongoose. But I did not mention any collection name. But data is getting saved when I sent data from Form as expected. I want to know that in which collection it will be stored by default. How to see the stored data.
how to mention specific collection name using mongoose if we want to save data in a particular collection.
3.Generally If we want to use any middleware in our app, we connect that
middleware using app.use() right? but in mongoose case, we do not add that
to app.use(). but still we can use the mongoose functionality.
could anyone please tell how it is possible.
Thanks a lot in advance.
How Mongoose interacts with MongoDB is described here.
It has this example:
var schema = new mongoose.Schema({ name: 'string', size: 'string' });
var Tank = mongoose.model('Tank', schema);
and mentions that
The first argument is the singular name of the collection your model is for. Mongoose automatically looks for the plural version of your model name. Thus, for the example above, the model Tank is for the tanks collection in the database.
model() takes a third argument where you can rename the collection:
var Tank = mongoose.model('Tank', schema, 'collectionname');
The collection gets made when model() is called.
app.use() is used for Express middleware. Mongoose isn't really that, which is why you're not using app.use() in this case.
This should probably be broken into multiple questions and you should probably show some code. That said, I'll take a crack at it.
Collection names are defined when you model your schema. So let's say you have:
const UserSchema = new Schema({
name: String
});
And then you later will tell mongoose to model it:
mongoose.model('User', UserSchema);
You'll have a collection called "users" in the database you're connecting to in your mongoose.connect() call.
Regarding middleware, Express middleware is specifically functions that you want to fire during the request/response cycle. You can still call code (e.g. mongoose) outside that cycle, and generally you'll connect to the database when the application starts and then read or save to it in either middleware or in your route handlers. For example, you might have a route like:
const User = mongoose.model('User');
app.get('/users', (req, res, next) => {
User.find({}, (err, users) => {
if (err) return next(err);
res.send(users);
});
});
In that case, you've got a route handler that calls mongoose through the User model previously defined.

Validation in MEAN stack .....?

I am developing a MEAN stack application but i stuck at validation(user-inputs). I know the client-side validations are done in Angular-JS but i am confused where to validate on server side. Either to use mongooose for validations or don't do any validation on mongooose(just store) do validations only in server(Node/express using some modules) or validate on both server-level and database-level....????
What should i do pls help me choose which practice is best.....????
Thanks.
As a MEAN stack developer there are various ways to validate the form...
1.) AngularJs form validations
2.) Mongoose Validation
3.) Backend Validation ( Express validator ot nodeValidator )
==> Validation in mongoose
Ex.
var userSchema = new Schema({
phone: {
type: String,
required: [true, 'User phone number required']
},
name: String,
subDoc: [
{
newName:String,
data:String
}
]
});
Above code shows simple integration of mongoose validator.
Validation in mongoose schema can create problems when writing the document
and worse situation can be generated when there are nested field and i am sure there will be. There are chances of modification of schema in such situation you to manage the validation, so much trouble i have faced..
So its a better IDEA to go with node validator or express validator which are super simple to use and provide lots of different type of validation options..
TRY
node-validator,
Express validator
js.com/package/node-validator
I personally suggest Express validator. which is simple and provide most of thing you need.
Banking just on mongoose validation is not enough. Your routes must be secured to not let invalid data pass through to mongoose validation.
The best place for this validation is middleware.
router.get('/', validateParameters, controller.index);
The function takes req, res and next. Call next if req parameters are valid, else respond with 400 status code. This way, only valid call reaches the end point.
function validateParameters(req, res, next){
// if req.params/req.body/req.query is valid
// return next();
// else return res.status(400).end;
}
As to actually how to validate, you can check express-validator package, which gives you lots of options to validate req body, query and params. One good option is creating a schema for each route and just passing that schema to validateParameters function and validating it with one of req.check(schema) (to check all), req.checkQuery(schema), req.checkBody(schema) orreq.checkParams(schema), depending on where your parameters are.
You may also want to take a look at mongoose-validatorjs.

Add a method to Express model

Let's suppose I have an Express model:
var SchemaDescription = {};
var Model = = new mongoose.Schema(SchemaDescription);
Express allows to tune up data validation in SchemaDescription. On save it works perfectly, but on update, because of mongoose nature, it isn't called, and there is no clean way to call it.
I tried Model.pre('update', ...); but didn't found the way to access/correct model's data before writing to the DB: because complex validation logics, which, for example, re-formats some data before checking.
A logical solution is to put validation code to save/update controller's handlers, but it leads to duplication of the code. To keep MVC pattern as for save, as for update, I'd like to put a public method to the model, or the schema, which gets input data and validate them.
My attempts look like:
Model.prototype.validate = function(input, isUpdate) {...};
or
SchemaDescription.validate = function(...) {...};
in different combinations.
The response always looks like "Cannot set property 'validate' of undefined"
Is there an approach to put a custom public function-member to an Express model/schema for being called in controllers?
What approach may be used to validate data on save and update, without code duplication, or/and putting validation logics to controllers?
You don't have an Express model, you have a Mongoose model. According to the latest documentation, you can explicitly activate validation on update: http://mongoosejs.com/docs/validation.html#update-validators

Extending MongoDB's "save" method in nodejs

In our app, we have a large document that is the source of most of our data for our REST api.
In order to properly invalidate our client-side cache for the REST api, i want to keep track of any modifications made to teh document. The best we came up with is to extend the mongo save command for the document to send off the notification (and then save as usual).
The question is, how does one actually do this in practice? Is there a direct way to extend mongo's "save" method, or should we create a custom method (i.e. "saveAndNotify") on the model that we use instead (which i would avoid if i can)?
[edit]
So in principle, i am looking to do this, but am having an issue not clobbering the parent save function();
mySchema.methods.save = function() {
// notify some stuff
...
//call mongo save function
return this.super.save();
};
Monkey patching the core mongo object is a bad idea, however it turns out mogoose has a middleware concept that will handle this just fine:
var schema = new Schema(..);
schema.pre('save', function (next) {
// do stuff
next();
});

Mongoose Model.count() does not run callback as documented

I am following almost the exact example for Model.count() from the Mongoose docs:
User.count({ type: 'jungle' }, function (err, count) {
console.log('I do not ever run');
});
This should print 'I do not ever run'. Instead, it returns a Query object - which should not happen, according to the docs, as I am providing a callback. How can I make the callback function run? Is there some circumstances where the callback is not run?
Using mongoose#3.6.17. Thanks!
Make sure you've connected to the database before calling any model functions. Mongoose will just queue up the count query until you connect otherwise.
See this question of the FAQ.

Resources