Mongoose ODM
NodeJS #5
Mongoose
- Schema-based solution to model,
- Validation,
- Query building,
- Hooks, ...
npm install --save mongoose
Installation locale
Un ODM fait le lien entre une base de données orientée Documents et des Object models
Mongoose
// index.js
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
Initialiser la connexion
var db = mongoose.connection;
db.on('error', console.log);
db.once('open', function() {
// we're connected!
});
Let's go !
Mongoose
connect()
.on('error', console.log)
.on('disconnected', connect)
.once('open', listen);
function listen () {
app.listen(port);
console.log('Express app started on port ' + port);
}
function connect () {
var options = { server: { socketOptions: { keepAlive: 1 } } };
return mongoose.connect(config.db, options).connection;
}
Start Express when Mongoose is ready ?!
Models
Schemas
const UserSchema = new mongoose.Schema({
name: { type: String, default: '' },
email: { type: String, default: '' },
username: { type: String, default: '' },
hashed_password: { type: String, default: '' },
salt: { type: String, default: '' },
authToken: { type: String, default: '' },
createdAt: { type: Date, default: Date.now }
});
mongoose.model('User', UserSchema);
Types : String, Number, Date, Buffer, Boolean, Mixed, ObjectId, Array
Models
Schemas (w/ subdocuments)
const getTags = tags => tags.join(',');
const setTags = tags => tags.split(',');
const ArticleSchema = new Schema({
title: { type : String, default : '', trim : true },
body: { type : String, default : '', trim : true },
user: { type : Schema.ObjectId, ref : 'User' },
comments: [{
body: { type : String, default : '' },
user: { type : Schema.ObjectId, ref : 'User' },
createdAt: { type : Date, default : Date.now }
}],
tags: { type: [], get: getTags, set: setTags },
image: {
cdnUri: String,
files: []
},
createdAt : { type : Date, default : Date.now }
});
Models
Validation built-in
var breakfastSchema = new Schema({
eggs: {
type: Number,
min: [6, 'Too few eggs'],
max: 12
},
bacon: {
type: Number,
required: [true, 'Why no bacon?']
},
drink: {
type: String,
enum: ['Coffee', 'Tea']
}
});
Models
Schemas (validation simple)
UserSchema.path('name').validate(function (name) {
return name.length;
}, 'Name cannot be blank');
Mongoose
Schemas (validation async)
UserSchema.path('email').validate(function (email, fn) {
const User = mongoose.model('User');
// Check only when it is a new user or when email field is modified
if (this.isNew || this.isModified('email')) {
User.find({ email: email }).exec(function (err, users) {
fn(!err && users.length === 0);
});
} else fn(true);
}, 'Email already exists');
Mongoose
Custom instance methods
// define a schema
var animalSchema = new Schema({ name: String, type: String });
// define a model
var Animal = mongoose.model('Animal', animalSchema);
// assign a function to the "methods" object of our animalSchema
animalSchema.methods.findSimilarTypes = function (cb) {
return this.model('Animal').find({ type: this.type }, cb);
}
var dog = new Animal({ type: 'dog' });
dog.findSimilarTypes(function (err, dogs) {
console.log(dogs); // woof
});
Mongoose
Custom static methods
// assign a function to the "statics" object of our animalSchema
animalSchema.statics.findByName = function (name, cb) {
return this.find({ name: new RegExp(name, 'i') }, cb);
}
var Animal = mongoose.model('Animal', animalSchema);
Animal.findByName('fido', function (err, animals) {
console.log(animals);
});
Mongoose
Hooks (middlewares)
var schema = new Schema(..);
// Before saving
schema.pre('save', function(next) {
// do stuff
next();
});
// After saving
schema.post('save', function(doc) {
console.log('%s has been saved', doc._id);
});
Models
Sauvegarde
var Tank = mongoose.model('Tank', yourSchema);
var small = new Tank({ size: 'small' });
small.save(function (err) {
if (err) return handleError(err);
// saved!
})
Models
Requêtes
var Person = mongoose.model('Person', yourSchema);
// find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields
Person.findOne({ 'name': 'Ghost' }, 'name occupation', function (err, person) {
if (err) return handleError(err);
console.log('%s is a %s.', person.name, person.occupation)
})
In mongoose 4, a Query has a .then() function, and thus can be used as a promise.
Models
Requêtes (JSON docs)
// With a JSON doc
Person.
find({
occupation: /host/,
'name.last': 'Ghost',
age: { $gt: 17, $lt: 66 },
likes: { $in: ['vaporizing', 'talking'] }
}).
limit(10).
sort({ occupation: -1 }).
select({ name: 1, occupation: 1 }).
exec(callback);
Models
Requêtes (Query builder)
// Using query builder
Person.
find({ occupation: /host/ }).
where('name.last').equals('Ghost').
where('age').gt(17).lt(66).
where('likes').in(['vaporizing', 'talking']).
limit(10).
sort('-occupation').
select('name occupation').
exec(callback);
Models
Suppression
Tank.remove({ size: 'large' }, function (err) {
if (err) return handleError(err);
// removed!
});
Reprendre l'exercice de la userslist et faire en sorte d'utiliser Mongo plutôt que la session pour le stockage des utilisateurs.
exercice
[NODEJS] MongoDB (cours 5)
By Julien Herpin
[NODEJS] MongoDB (cours 5)
- 1,712