Outils pour utilisateurs

Outils du site


web:javascript:mean_stack:mongoose

Mongoose

Mongoose est un Object Document Mapper (ODM) utilisé pour MongoDB, en opposition à un Object Relational Mapper (ORM) utilisé dans les bases de données relationnelles.

Installation

L'installation de Mongoose se fait avec npm :

$ npm install mongoose

On peut utiliser les options -g ou --save si nécessaire. Voir la rubrique sur npm pour plus de détails.

Schema

Simple

Créer un schema est plutôt simple. À la base, il faut spécifier les champs et leur type :

var simpleSchema = new Schema({ fieldName: SchemaType });

Un exemple plus complet ressemblerait à ceci :

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
 
var customerSchema = new Schema({
  name:      String,
  address:   String,
  city:      String,
  state:     String,
  country:   String,
  zipCode:   Number,
  createdOn: Date,
  isActive:  Boolean
});

Valeurs par défaut

  created: {
    type: Date,
    default: Date.now
  }

Types de données

Mongoose Data Type Javascript Data Type
String String
Number Number
Date Object
Buffer Object
Boolean Boolean
Mixed Object
ObjectId Object
Array Array (Object)

Schema plus complexe

On peut insérer des schemas à l'intérieur de schemas. Par exemple, un client a une adresse. Le client lui-même est un schema, mais l'adresse peut l'être aussi.

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
 
var addressSchema = new Schema({ type: String,
  street: String,
  city: String,
  state: String,
  country: String,
});
 
var customerSchema = new Schema({
  name: {
    first: String,
    last: String
  },
  address: [ addressSchema ],
  createdOn: { type: Date, default: Date.now },
  isActive: { type: Boolean, default: true}
});

Il faut remarquer que la propriété address de customerSchema est un tableau avec addressSchema.

Précisions sur les propriétés

Propriété _id

Par défaut, quand on spécifie pas de propriété identité, à l'instance de _id, cette propriété est ajoutée automatiquement par MongoDB à l'ajout d'un document. La valeur par défaut de cette propriété est un ObjectId. On peut dire à Mongoose, dans le schéma, de ne pas ajouter cette propriété en lui assignant false.

var noIdSchema = new Schema({ name: String }, { _id: false });

Propriété type

Si on prend l'exemple ci-dessous, on pourrait se demander pourquoi ne pas nommer questionType tout simplement type ?

var subQuestions = {
  questionType: String,
  questionText: String,
  answers: [ subAnswers ] };

Les schemas de Mongoose ne peuvent pas contenir de propriété type. Cette propriété a une signification. Celle-ci dit que le document doit être casté au type spécifié. Par exemple, si on change questionType: String pour type: String, l'objet sera casté en String et quand ce sera sauvegardé dans MongoDB, on verra type: [object Object].

Si on veut une propriété type, on peut faire type: {type: String} :

var subQuestions = {
  type: { type: String },
  text: String,
  answers: [ subAnswers ] };

Ajout de propriétés

Avec add() utilisé sur un schema, on peut ajouter des propriétés. Ceci est utile par exemple pour avoir des propriété à certaines conditions.

var exempleSchema = new Schema({
  name: String
});
 
exempleSchema.add({
  address: String
});

Modèle

Création

La création d'un modèle se fait avec mongoose.model(). Le premier argument de model() est le nom du modèle et le second est le schema. Normalement, le nom du modèle est singulier et sera plurialisé lors de la création de la collection sur MongoDB.

Dans le cas suivant, le nom du modèle est Person, mais la collection devrait s'appeler People.

var personSchema = new Schema({
  firstName: String,
  lastName: String
});
 
var Person = mongoose.model('Person', personSchema);

Instanciation

var bob = new Person({
  firstName: 'Bob',
  lastName: 'Doe'
});

Sauvegarde

bob.save(callback);

Requêtes

find

La signature de find() :

Model.find(conditions, fields, options, callback);

Pour retrouver tous les documents d'un modèle, avec aucun callback et une exécution différée :

var allPeople = People.find();
 
allPeople.exec(function (err, results) {
  // Gérer l'erreur ou le résultat
});

Avec un callback, exécute la requête immédiatement :

Standup.find(function (err, results) {
  // Gérer l'erreur ou le résultat
}); 

Avec un callback et des conditions :

Standup.find({ memberName: 'David' }, function (err, results) {
  // Gérer l'erreur ou le résultat
});

Limiter les propriétés retournés :

Standup.find({ memberName: 'Mary' }, 'memberName impediment',
  function (err, results) {
 
});

Exemple d'options :

var query = Standup.findOne({ memberName: 'Bob'}, null, { limit: 10 });

findOne

Signature :

Model.findOne(conditions, [fields], [options], [callback])

Exemple sans callback et sans condition :

var Standup = require('../models/standup.server.model.js');
 
var query = Standup.findOne();
query.exec(function (err, results) {
  // gérer le résultat / l'erreur
});

Exemple avec un callback :

var query = Standup.findOne({ memberName: 'Mark' });

findById

Signature :

Model.findById(id, [fields], [options], [callback])
var id = '541c6fefefdf9c84172162a6';
var query = Standup.findById(id);
 
query.exec(function (err, doc) {
  // gérer le résultat / l'erreur
});

Même exemple que plus haut, mais avec la méthode chaînée :

Standup.findById(id).exec(function (err, results) {
  // gérer le résultat / l'erreur
});

Exemple pour trouver un document par id qui retourne tous les propriétés sauf impediment. Le moins - devant sert à soustraire des champs.

var query = Standup.findById(id, '-impediment');

Opérateurs de comparaison

Des opérateurs peuvent être utilisés dans les requêtes pour affiner les résultats. Ce sont les mêmes qu'utilisés dans MongoDB.

Les opérateurs de comparaison pour les requêtes
$gt greater than
$gte greater than or equal to $in exists in
$lt less than
$lte less than or equal to $ne not equal to
$nin does not exist

Exemple :

Customer.find({discount: {$gte: 10}, function(err, results) {
  if (err) throw err;
  console.log(results);
});

where

Au lieu d'utiliser une méthode find() comme celle-ci :

Customer.find({discount: {$gte: 10, $lt: 20}, function(err, results) {
  // code ...
});

On peut utiliser la méthode where() qui est chaînable :

Customer.where('discount').gte(10).lt(20).exec(function(err, results) {
  // code ...
});

Autre exemple avec plusieurs where() chaînés :

Customer.where('discount').gte(10).lt(20)
        .where('zipCode', '12345')
        .exec(function(err, results) {
          // code ...
        });

Mise à jour

Pour mettre à jour un document, on peut le récupérer et le sauvegarder dans le callback :

Standup.findById(id).exec(function (err, doc) {
  // Mise à jour ...
  doc.impediment('None');
  doc.save(function (err) {
    // code du callback save.
  });
});

Le code ci-haut fait en sorte de faire deux requêtes. Il est préférable d'utiliser update() :

Model.update(conditions, update, [options], [callback])
var condition = { memberName: 'Mary' };
var update = { impediment: 'None – Mary no longer works here!' };
 
Standup.update(condition, update, function(err, numberAffected, rawResponse) {
  // code du callback
});

Options de l'update

Option Description Default Value
safe Safe mode – default to value set in schema True
upsert Create the document if it does not match False
multi Determines if multiple documents should be updated or not False
strict Override the strict option for this update
overwrite Disables the update-only mode to allow for overwrite of document False

Exemple qui montre la mise à jour de plusieurs documents qui matchent :

var condition = { firstName: 'Bob' };
var update = { firstName: 'Robert' };
 
Customer.update(condition, update, { multi: true },
function(err, numberAffected, raw) {
  // code du callback
});

findByIdAndUpdate

Option Description Default Value
new Set to true to return the modified document rather than the original. True
upsert Create the document if it does not match False
select Specify the document fields to return

Suppression

Signature

Model.remove(conditions, [callback])
var condition = { memberName: 'Mary' };
 
Standup.remove(condition, function(err) {
  // code callback
});

Supprimer tous les documents qui sont créés le ou après le 31 octobre 2014:

var gteDate = new Date(2014, 10, 31);
 
Standup.remove({ createdOn: { $gte: gteDate }}, function (err) {
  // code callback
});

Suppression sans callback :

var query = Standup.remove({ createdOn: { $gte: gteDate }});
query.exec();

findByIdAndRemove

Option Description Default Value
select Specify the document fields to return

Autres exemples de requêtes

var query = Standup.find();
 
query.sort({ createdOn: 'desc' })
     .limit(10)
     .exec(function(err, results) {
       // code callback
     });

Validation

Schema Type Built-in Validators
String required enum match
Number required min max
Date required
Buffer required
Boolean required
Mixed required
ObjectId required
Array required

Validation required

Exemple de schema :

var customerSchema = new Schema({
  name: { type: String, required: true }, address: String,
  city: String,
  state: String,
  country: String,
  zipCode: Number,
  createdOn: Date,
  isActive: Boolean
});

Une fois le schema définit, on peut préciser une validation avec required(). La signature est:

required(required, [message])
customerSchema.path('city').required(true, ‘Oops! Supply a city.’);

Validation match

var reMatch = /[a-zA-Z]/;
var customerSchema = new Schema({
  name: { type: String,
          required: true,
          match: reMatch },
         // etc...
});

Validation enum

var impediments = ['none', 'minor', 'blocking', 'severe'];
 
var standupSchema = new Schema({
  // abbreviated...
  impediment: {
    type: String,
    required: true,
    enum: impediments
  }
});

Validation min et max

var customerSchema = new Schema({
  name: String,
  discount: { type: Number, min: 5 }
});
 
var customerSchema = new Schema({
  name: String,
  discount: { type: Number, max: 60 }
});
 
var customerSchema = new Schema({
  name: String,
  discount: { type: Number, min: 5, max: 60 }
});

Validation personnalisée

Une validation personnalisée peut être spécifiée avec validate. L'important, c'est que la fonction du validateur retourne true ou false, indiquant que la validation est correcte ou non.

var sizeValidator = [
  function (val) {
    return (val.length > 0 && val.length <= 50)
  },
  // Custom error text...
  'String must be between 1 and 50 characters long'
];
 
var personSchema = new Schema({
  firstName: { type: String, required: true, validate: sizeValidator },
  lastName: { type: String, required: true, validate: sizeValidator },
  status: { type: String, required: true, default: 'Alive' }
});
 
var Person = new mongoose.model('Person', personSchema);
 
var newPerson = new Person( { firstName: 'John', lastName: 'Doe' } );
 
newPerson.save(function (err) {
  if (err) return handleError(err);
  // saved the person document!
});
web/javascript/mean_stack/mongoose.txt · Dernière modification : 2022/02/02 00:42 de 127.0.0.1