プラグイン

スキーマはプラグイン可能です。つまり、あらかじめパッケージ化された機能を適用して機能を拡張することができます。これは非常に強力な機能です。

プラグインは、複数のスキーマでロジックを再利用するためのツールです。データベースに複数のモデルがあり、各モデルにloadedAtプロパティを追加したいとします。プラグインを一度作成して、それぞれのスキーマに適用します

// loadedAt.js
module.exports = function loadedAtPlugin(schema, options) {
  schema.virtual('loadedAt').
    get(function() { return this._loadedAt; }).
    set(function(v) { this._loadedAt = v; });

  schema.post(['find', 'findOne'], function(docs) {
    if (!Array.isArray(docs)) {
      docs = [docs];
    }
    const now = new Date();
    for (const doc of docs) {
      doc.loadedAt = now;
    }
  });
};

// game-schema.js
const loadedAtPlugin = require('./loadedAt');
const gameSchema = new Schema({ /* ... */ });
gameSchema.plugin(loadedAtPlugin);

// player-schema.js
const loadedAtPlugin = require('./loadedAt');
const playerSchema = new Schema({ /* ... */ });
playerSchema.plugin(loadedAtPlugin);

ゲームとプレイヤーの両方のスキーマにロード時間の動作を追加し、ゲームのloadedAtパスにインデックスを宣言しました。数行のコードで実現できました。

グローバルプラグイン

すべてのスキーマ用のプラグインを登録したいですか? mongooseのシングルトンには、すべてのスキーマ用のプラグインを登録する.plugin()関数があります。例えば

const mongoose = require('mongoose');
mongoose.plugin(require('./loadedAt'));

const gameSchema = new Schema({ /* ... */ });
const playerSchema = new Schema({ /* ... */ });
// `loadedAtPlugin` gets attached to both schemas
const Game = mongoose.model('Game', gameSchema);
const Player = mongoose.model('Player', playerSchema);

モデルをコンパイルする前にプラグインを適用

多くのプラグインはミドルウェアに依存するため、mongoose.model()またはconn.model()を呼び出す前にプラグインを適用するようにする必要があります。そうしないと、プラグインが登録するミドルウェアは適用されません

// loadedAt.js
module.exports = function loadedAtPlugin(schema, options) {
  schema.virtual('loadedAt').
    get(function() { return this._loadedAt; }).
    set(function(v) { this._loadedAt = v; });

  schema.post(['find', 'findOne'], function(docs) {
    if (!Array.isArray(docs)) {
      docs = [docs];
    }
    const now = new Date();
    for (const doc of docs) {
      doc.loadedAt = now;
    }
  });
};

// game-schema.js
const loadedAtPlugin = require('./loadedAt');
const gameSchema = new Schema({ /* ... */ });
const Game = mongoose.model('Game', gameSchema);

// `find()` and `findOne()` hooks from `loadedAtPlugin()` won't get applied
// because `mongoose.model()` was already called!
gameSchema.plugin(loadedAtPlugin);

公式サポートされているプラグイン

Mongooseチームは、Mongooseに新しいクールな機能を追加するプラグインをいくつか保守しています。以下にいくつか紹介します。

正式にサポートされているプラグインの全リストは、Mongooseのプラグイン検索サイトにあります。

コミュニティ

独自のプロジェクトでスキーマ機能を再利用できるだけでなく、Mongooseコミュニティの利点も享受できます。 npmに公開されており、「mongoose」がnpmキーワードとして含まれるプラグインはすべて、検索結果ページに表示されます。