[Mongoose] 途中から field に default 定義を追加する場合の実装方針

Mongoose で途中から field に default 定義を追加する場合の実装方針をご紹介します。

mongoose | マングース

var mongoose = require('mongoose');
 
var orderSchema = new mongoose.Schema({
  // 合計金額
  amount: {
    type: Number
  },
  // 送料無料の条件が適用される閾値 (単位: USD)
  freeShippingThreshold: {
    type: Number,
    default: 100
  }
});
 
var Order = mongoose.model('Order', orderSchema);
 
 
/**
 * Case1: 新規 instance
 * instance 化されたときはデフォルト値が入った状態で便利
 **/
var order = new Order();
/**
 * order : {
 *    _id: 5512abca1c6bb890a82b0951,
 *    freeShippingThreshold: 100
 * }
 **/
 
 
/**
 * Case2: MongoDB に保存されている既存データから取得した instance
 *
 * MongoDB に保存されているデータは下記の通り
 * 
 * order : {
 *   _id: 50169294b1b4a1c21e00001e,
 *   amount: 150
 * }
 **/
Order.findOne(function (err, order) {
  /**
   * Mongoose の findOne method で instance 取得したときは、
   * 値が入ってなければ default に設定した値がセットされる
   * 
   * order : {
   *   _id: 50169294b1b4a1c21e00001e,
   *   amount: 150,
   *   freeShippingThreshold: 100
   * }
   **/
});

Case1 の新規インスタンスを作成するケースは、デフォルトで freeShippingThreshold に 100 が入ってるので、使い回しが便利です。何の問題もなさそうですね。

Case2 は既に MongoDB に保存されているが freeShippingThreshold に値が入ってないので、 100 が入った状態で order インスタンスを取得できます。しかし、この order が保存されたときはキャンペーン期間中で送料無料の閾値が $50 になっていたので 50 が入ったデータが欲しいわけです。こういうケースは後から default: 100 を設定するタイミングで既存データに適切な freeShippingThreshold を設定してあげる必要があるわけです。

以上、うっかりしてると陥るかもしれない Mongoose の運用事例を現場からお送りしました。