2011-10-30 16 views
5

私はMongooseを使用してPersonTransactionコレクションをモデル化しています。それぞれのTransactionは2つの異なるPersonインスタンスへの参照を持ちます:Mongoose:外部キー/逆関係をモデル化する方法は?

var TransactionSchema = new Schema({ 
    , amount   : { type: Number, required: true } 
    , from   : { type: ObjectId, required: true } 
    , to    : { type: ObjectId, required: true } 
    , date   : Date 
}); 

var PersonSchema = new Schema({ 
    name   : { type: String, required: true } 
    , transactions : [ObjectId] 
}); 

それぞれのPersonにすべてのTransactionのコレクションを持たせたいのtoまたはfrom値。これまでのところ、これは私がそれを行う方法を理解することができる最良の方法です:

TransactionSchema.pre('save', function(next, done) { 
    var transaction = this; 

    Person.findById(this.to, function (err, person) { 
     person.transactions.push(transaction); 
     person.save(); 
    }); 

    Person.findById(this.from, function (err, person) { 
     person.transactions.push(transaction); 
     person.save(); 
    }); 

    next(); 
}); 

これは過剰です。もっと良い方法がありますか、あるいはMongoDBをリレーショナルデータベースのように使いすぎていますか?各Personインスタンスに関連付けられたTransactionのコレクションを持つ代わりに、Translationコレクションを直接クエリするだけでいいですか?

ありがとうございます。

答えて

7

MongoDBスキーマを設計するときに、データベースで実行するクエリについてさらに考える必要があります。

速度のためにデータを複製し、完全性のために参照しようとします。どういう意味ですか?
たとえば、トランザクションのクエリを作成するときなど、初めてのユーザーの詳細をすべて必要としないと思いますか?だからではなく、

var TransactionSchema = new Schema({ 
    , amount   : { type: Number, required: true } 
    , from   : { 
    user_id: { 
     type: ObjectId 
    , required: true 
    } 
    , username: { 
     type: String 
    , required: true 
    } 
    } 
    , to    : { 
    user_id: { 
     type: ObjectId 
    , required: true 
    } 
    , username: { 
     type: String 
    , required: true 
    } 
    } 
    , date   : Date 
}); 

:(?トランザクションの情報を表示するときに、ユーザーの電子メール、場所を必要としない)
私はあなたがこのような何かを行う必要がありますので、あなただけの、おそらく、ユーザーIDとユーザー名が必要だと思いますトランザクションの詳細が表示されているページ(トランザクション用とユーザー名用の2つのクエリ)を表示する3つのクエリを実行すると、1つだけ表示されます。
これは単なる例です。達成しようとしていることに応じて、Userスキーマに同じロジックを適用できます。

とにかく、ミドルウェアは大丈夫​​だとは思いません。エラーをチェックしているわけではありません。これは(テストが、アイデアは重要ではありませんでした)私はミドルウェアを書くだろうかです:

私は、フロー制御のための Stepライブラリを使用していると私は一つだけのクエリを使用しています上記のコードで
TransactionSchema.pre('save', function(next, done) { 
    var transaction = this; 

    Person.where('_id').in([this.to, this.from]).run(function (err, people) { 
    if (people.length != 2) { next(new Error("To or from doesn't exist")); return; } 
    Step(
     function save_to() { 
     people[0].transactions.push(transaction); 
     people[0].save(this); 
     }, 
     function save_from(err) { 
     if (err) { next(err); return; } 
     people[1].transactions.push(transaction); 
     people[1].save(this); 
     }, 
     function callback(err) { 
     next(err); 
     } 
    ); 
    }); 
}); 

2つではなく(「to」と「from」を検索する場合)

+0

muchos!ちょうど私が読む必要があった –

+0

これは、保存前または保存後にこれを行う方が良いですか?検証エラーまたはその他のエラーのためにトランザクションが保存されない場合はどうなりますか。あなたはダミーアイテムを直接追加していませんか?ポストセーブでこれを行うと、トランザクションを再度クエリする必要はありません – raju

関連する問題