熊手マングース

ハッカー-納屋に隠れてロックされている熊手を踏む男


Mongooseは、最も人気のあるjavascript mongodbモジュールです。 このサイトのサンプルを使用すると、すばやく正常に使用を開始できますが、mongooseには、プログラマーが頭の毛を引き裂き始める可能性のある多くの予期しない機能があります。 これらの機能について説明します。



1.コレクションの命名



最も無害で簡単に検出できる機能から始めます。 モデルを作成します:



var mongoose = require('mongoose'); var User = new mongoose.Schema({ email: String, password: String, data: { birthday: { type: Date, default: Date.now }, status: { type: String, default: 'active', enum: ['active', 'unactive'] }, mix: { type: mongoose.Schema.Types.Mixed, default: {} } } }); module.exports = mongoose.model('User', User);
      
      





ユーザーを作成します。



 var user = new User({email: 'test@test.com', password: '12345'}); user.save(ok(function() { console.log('ok'); }));
      
      





mongodbコンソールで「show collections」コマンドを実行すると、usersコレクションが作成されたことがわかります。 つまり コレクションを作成する際のmongooseは、名前を小文字と複数形に変換します。



2. toJSON()メソッドのオーバーライド



モデルに記述されていない属性をモデルインスタンスに導入して、モデルインスタンスを変更する必要があるとします。



 User.findOne({email: 'test@test.com'}, ok(function(user) { user.someArea = 'custom value'; console.log(user.someArea); console.log('===='); console.log(user); }));
      
      





コンソールに表示されます(console.logの代わりにres.jsonを使用できます)。



 custom value ==== { __v: 0, _id: 54fc8c22c90fb7dd025eee7c, email: 'test@test.com', password: '12345', data: { mix: {}, status: 'active', birthday: Thu Mar 12 2015 23:46:06 GMT+0300 (MSK) } }
      
      





ご覧のとおり、オブジェクトには属性someAreaがありますが、コンソールにダンプされると、突然どこかで消えました。 問題は、mongooseがtoJsonメソッドをオーバーライドし、モデルダイアグラムに記述されていないすべてのフィールドがスローされることです。 オブジェクトに属性を追加してクライアントに渡すと、状況が発生する場合がありますが、属性はクライアントに到達しません。 クライアントを正常にヒットさせるためには、mongooseオブジェクトではなく変更する必要があります。 これらの目的のために、モデルインスタンスにはtoObjectメソッドがあり、ネイティブオブジェクトを返します。このオブジェクトは必要に応じて変更でき、何も失われません。



3. _idの比較



_idはString型のように見えるかもしれませんが、そうではありません。 _id-オブジェクトであり、mongoose-modelインスタンスの識別子をオブジェクトとして比較します。 例:



 User.findOne({email: 'test@test.com'}, ok(function(user1) { User.findOne({email: 'test@test.com'}, ok(function(user2) { log(user1._id == user2._id); // false log(user1._id.equals(user2._id)); // true log(user1._id.toString() == user2._id.toString()); // true })); }));
      
      







4.混合フィールドの保存



スキーマにタイプが混在するフィールドが1つあります。これはdata.mixです。 たとえば、変更する場合:



 User.findOne({email: 'test@test.com'}, ok(function(user) { user.data.mix = {msg: 'hello world'}; user.save(ok(function() { console.log('ok'); })); }));
      
      





、変更がデータベースに正常に反映されます。



ただし、data.mix内で変更を加えた場合、データベースには変更が加えられません。



 User.findOne({email: 'test@test.com'}, ok(function(user) { user.data.mix.msg = 'Good bye'; user.save(ok(function() { log(user); })); }));
      
      





変更を含むユーザーオブジェクトがコンソールに表示され、データベースへのクエリはユーザーが変更されていないことを示します。 変更がデータベースに反映されるようにするには、混合フィールドを変更したことをsaveメソッドの前にmongooseに通知する必要があります。



 user.markModified('data.mix');
      
      





組み込みメソッド(setMonth、setDate、...)によって変更された場合、Date型オブジェクトでも同じ操作を実行する必要があります。これはドキュメントに記載されています



5.配列のデフォルト



モデルダイアグラムを記述するときに、フィールドにオブジェクトの配列を配置することを決定したとします。 配列自体およびその中にネストされたすべてのオブジェクトのデフォルトを登録する必要があります。 Mongooseはこれに特別なタイプのキーを使用します。



 var Lib = new mongoose.Schema({ userId: mongoose.Schema.ObjectId, images: { //           images type: [{ uploaded: { type: Date, default: Date.now }, src: String }], //  -   images default: [{uploaded: new Date(2012, 11, 22), src: '/img/default.png'}] } }); module.exports = mongoose.model('Lib', Lib);
      
      





同様に、typeキーワードを使用して、オブジェクトのマルチレベルのデフォルトを作成できます。



6.ストリーミング更新



非常に大きなコードのコレクションを更新する必要がある場合があります。 コレクション全体のダウンロードはメモリ不足です。 手動で制限を設定し、ドキュメントをバッチでロードして更新できますが、mongooseにはこの操作に非常に便利なインターフェイス(ストリーム)があります。



 emusers.find({}).stream() .on('data', function(user) { var me = this; me.pause(); //        user.save(function(err) { me.resume(err); }); }) .on('error', function(err) { log(err); }) .on('close', function() { log('All done'); });
      
      





(ただし、ユーザーをバッチで抽出し、async.parallelを使用して編集および保存すると、少し速くなりますが、読みにくくなります)。



6.自動インデックス構築の無効化



Mongodbは、一意のインデックスを使用してフィールドの一意性を確保します。 マングースを使用すると、非常に簡単に作成できます。 Mongooseは通常、データを操作するときに高レベルの抽象化を作成します。 しかし、私たちの欠点は私たちの利点の継続であり、多くは公式モードで明確に述べられていますが、本番モードでインデックスの自動作成をオフにすることを忘れています

これらの目的のためのmongooseには、特別なフラグ{autoIndex:false}があり、データスキームを記述するときに指定する必要があります。



 var User = new mongoose.Schema({ email: { type: String, unique: true, required: true }, password: String }, { autoIndex: process.env('mode') == 'development' });
      
      





現在、自動インデックス作成は開発モードでのみ機能します。



7.予約されたキーを忘れないでください



おそらく誰もが同様の問題に直面しているわけではありませんが、それでもマングースオブジェクトには属性の予約名のセットがあるという事実に注意を払います 。 予約リストのキーを使用して属性の命名を処理する必要がありました。その後、コード全体でこれらのキーの呼び出しをスクラブする必要がありました。 Mongooseは、予約キーの使用を誓いません。 このキーのリストで踏んだレーキは、オプションキーであることが判明しました。



All Articles