3
votes

I came across a bit of a design problem with Mongoose - but maybe I am following the wrong approach?

In good old OOP style I want to have a class called User. The class has several member such as username, firstname, lastname, salt and hash, and it has a method called authenticate which takes a hashed password as an argument. However to fill my User object with data, I need to write code like this, as far as I am aware:

    var userSchema = mongoose.Schema({
    firstName: String,
    lastName:  String,
    userName: String,
    salt: String,
    hashed_pwd:String

});

userSchema.methods =  {
    authenticate: function(passwordToMatch) {

        return crypto.hashPwd(this.salt, passwordToMatch) === this.hashed_pwd;
    }
}

This code is cluttered with Mongoose specific code - calling mongoose.Schema, and to add the method I have to use userSchema.methods. When I tried to declare my User class separately and tried to create the Mongoose Schema out of it, I encountered all kinds of errors, and the member method was not recognised.

So when I want to use a different database using the same schema, I have to redeclare everything. But I want to declare all my schemas separately as they will reoccure all over the place in my application.

Is there any elegant solution to this, is there a different library I can use, or am I following a completely wrong approach?

thanks in advance..

1

1 Answers

4
votes

This is perhaps a partial answer, but it might help guide you in a useful direction.

It's worth understanding what mongoose is and what it does. Mongoose is an ODM (not an ORM—read here for the difference. TL;DR: ODM is to NoSQL as ORM is to SQL; non-relational DB to relational DB.) Mongoose helps abstract some of the boilerplate boring stuff like validations; stuff you want when dealing with a data in or being written into a database. The basis of this validation comes from mongoose.Schema with which you define what each model should contain and what each property on a model should be cast as (i.e. username should be a string, updatedOn should be a datestamp.)

If you want your code to be database-agnostic (that is, not requiring any specific database), Mongoose is not what you're looking for. If not being tied to any specific DB is important to you, you should try looking for a database agnostic ORM/ODM. At the moment, Waterline comes to mind.

It should be mentioned that, if you don't care about validations, data casting, etc. that mongoose provides, you could just roll vanilla MongoDB queries and stick whatever JSON-compatible JavaScript object into your (NoSQL) database. But this is not recommended unless you fully understand what you lose / risk in doing so.

I might also argue that, the authenticate method has no place being in your model and should instead exist in a position previous to any model/database interaction (e.g. in a controller or the equivalent if you're not following MVC conventions.)