2011-12-17 174 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); 
    }