2011-12-17 9 views
17

私は、モバイルクライアントを同期するために、私のアプリのログキーパーとしてMongoDBを使用しています。マングース:入力されたフィールドを埋め込む

var UserArticle = new Schema({ 
    date: { type: Number, default: Math.round((new Date()).getTime()/1000) }, //Timestamp! 
    user: [{type: Schema.ObjectId, ref: "User"}], 
    article: [{type: Schema.ObjectId, ref: "Article"}], 
    place: Number,  
    read: Number,  
    starred: Number, 
    source: String 
}); 
mongoose.model("UserArticle",UserArticle); 

var Log = new Schema({ 
    user: [{type: Schema.ObjectId, ref: "User"}], 
    action: Number, // O => Insert, 1 => Update, 2 => Delete 
    uarticle: [{type: Schema.ObjectId, ref: "UserArticle"}], 
    timestamp: { type: Number, default: Math.round((new Date()).getTime()/1000) } 
}); 
mongoose.model("Log",Log);

私はfollwingコードを使用するログretriveしたい:あなたが見ることができるように


var log = mongoose.model('Log'); 
log 
.where("user", req.session.user) 
.desc("timestamp") 
.populate("uarticle") 
.populate("uarticle.article") 
.run(function (err, articles) { 
if (err) { 
    console.log(err); 
     res.send(500); 
    return; 
} 
res.json(articles); 

が、私はマングースを移入したい「とuarticle」私はNodeJSに設定し、このモデルを持っていますフィールドをLogコレクションから取得し、次にUserArticle( "uarticle")の "article"フィールドに値を設定します。

しかし、このコードを使用すると、Mongooseは、UserArticle Modelを使用して "uarticle"にデータを取り込みますが、uarticle内の記事フィールドは読み込みません。

Mongooseを使用してpopulate()を実行するか、別の処理を行う必要がありますか?

は、私が文書で確認したものから、私はあなたから聞くから、

+0

私は参照が中に埋め込まれているのと同じ問題に遭遇しました配列 - > myList:[{mid:{type:Schema.ObjectId、 'ref': 'OtherModel'}、メタ:[String]}]。これは、私は.populate( 'myList.mid')を試してみると、次のエラーが発生します... TypeError:未定義のメソッド 'path'を呼び出すことができません – Greg

答えて

16

をありがとう、これを達成することはできませんが、コールバック関数に「uarticle.article」のドキュメントを自分で取り込むことができます。

しかし、私はより重要と考える別の側面を指摘したいと思います。コレクションBを参照するコレクションAのドキュメントがあり、コレクションBのドキュメントにコレクションCのドキュメントに関する別の参照があります。

これは間違っている(データベース構造を参照している)か、ここでMySQLなどのリレーショナルデータベースを使用してください。 MongoDBの能力は、より多くの情報をドキュメントに埋め込むことができるため、より少ないクエリ(単一のコレクション内にデータを持つ)を作成する必要があるという事実に依存しています。あなたがMongoDBを最大限に活用しているように、何かを参照することは大丈夫ですが、参照を持っていて別の参照がないように見えます。

あなたの状況とデータベース構造を分かち合いたいと思うかもしれません。以下のようなものについてはどのように

+0

ログコレクションは奇妙な参照を持っている唯一のものです(同じデータを何度も繰り返すのを避けるために)参照が1つしかありません。多くの情報を使わないようにするために、私はこれを "uarticle"に設定しません。クライアントは物事をシンプルで速く保つために、記事の詳細を入手するよう要求します。 – Francesc

+1

あなたはあなたの答えをもっと詳しく説明できますか?私はそれを正しく読んでいます。私はちょうどmongodbで始めています。結局のところ、多くのリレーショナル表には1つの外部キーしかありません。埋め込まれたドキュメントは、ObjectIdの参照を移入するほうが望ましいですか? – grantwparks

+0

それは本当にプロジェクトの構造に依存しています。時には、高速化のためにデータ(埋め込み)を複製したい場合もありますが、そのデータは特定の条件でのみクエリされるため、参照する必要があります。 – alessioalex

0

populate_deep = function(type, instance, complete, seen) 
{ 
    if (!seen) 
    seen = {}; 
    if (seen[instance._id]) 
    { 
    complete(); 
    return; 
    } 
    seen[instance._id] = true; 
    // use meta util to get all "references" from the schema 
    var refs = meta.get_references(meta.schema(type)); 
    if (!refs) 
    { 
    complete(); 
    return; 
    } 
    var opts = []; 
    for (var i=0; i<refs.length; i++) 
    opts.push({path: refs[i].name, model: refs[i].ref}); 
    mongoose.model(type).populate(instance, opts, function(err,o){ 
    utils.forEach(refs, function (ref, next) { 
     if (ref.is_array) 
     utils.forEach(o[ref.name], function (v, lnext) { 
      populate_deep(ref.ref_type, v, lnext, seen); 
     }, next); 
     else 
     populate_deep(ref.ref_type, o[ref.name], next, seen); 
    }, complete); 
    }); 
} 

メタutilsの荒れている... SRCをしたいですか?

5

これを行うには、mongoose-deep-populateプラグインを使用できます。使用法:

User.find({}, function (err, users) { 
    User.deepPopulate(users, 'uarticle.article', function (err, users) { 
     // now each user document includes uarticle and each uarticle includes article 
    }) 
}) 

免責事項:私はプラグインの作成者です。

1

私は同じ問題に直面したが、努力の時間の後、私はsolution.Itは、任意の外部プラグインを使用せずにすることができ見つける:)

applicantListToExport: function (query, callback) { 
     this 
     .find(query).select({'advtId': 0}) 
     .populate({ 
      path: 'influId', 
      model: 'influencer', 
      select: { '_id': 1,'user':1}, 
      populate: { 
      path: 'userid', 
      model: 'User' 
      } 
     }) 
    .populate('campaignId',{'campaignTitle':1}) 
    .exec(callback); 
    } 
関連する問題