2011-12-17 223 views
17

我正在使用MongoDB作爲日誌管理器來爲我的應用程序同步移動客戶端。我有這個模型中的NodeJS設置:貓鼬:填充填充的字段

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代碼日誌:


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」字段從日誌集合,然後,我想填充UserArticle(「uarticle」)的「文章」字段。

但是,使用此代碼,Mongoose僅使用UserArticle模型填充「uarticle」,但不填充uarticle內部的文章字段。

是否有可能使用Mongoose和populate()完成它,或者我應該做別的事情?

謝謝

+0

我碰到其中基準嵌入了同樣的問題一個數組 - > myList:[{mid:{type:Schema.ObjectId,'ref':'OtherModel'},meta:[String]}]。當我嘗試.populate('myList.mid')時會產生以下錯誤... TypeError:無法調用未定義的方法'path' – Greg 2011-12-21 20:00:05

回答

16

從我的文檔中已經檢查過,從我收到你的來信,這是無法實現的,但你可以自己填入「uarticle.article」文件裏的回調函數。

但是我想指出另一個我認爲更重要的方面。你必須在集合的文件,其中引用集合B,並在集合B的文件,你有另一種參考集合C.文件

您可能是這樣做不對(我指的是數據庫結構),或者你應該在這裏使用像MySQL這樣的關係數據庫。 MongoDB的功能依賴於您可以在文檔中嵌入更多信息的事實,因此必須進行較少的查詢(將數據存儲在單個集合中)。儘管引用某些東西是可以的,但引用和引用其他引用似乎並沒有在這裏充分利用MongoDB的優勢。

也許你想分享你的情況和數據庫結構,所以我們可以幫助你更多。

+0

Logs集合是唯一一個有奇怪引用的我只想要的,因爲其他只有1個參考(避免重複很多次相同的數據)。我認爲爲了避免使用大量的信息,我不會填充這個「uarticle」,客戶會請求獲得文章的詳細信息,只是爲了保持簡單和快速。 – Francesc 2011-12-17 12:42:00

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); 
    }