我正在使用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);
当我想要检索日志时,我使用以下代码:
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);
正如您所看到的,我希望mongoose从Log集合中填充“uarticle”字段,然后,我想填充UserArticle(“uarticle”)的“article”字段。
但是,使用此代码,Mongoose仅使用UserArticle模型填充“uarticle”,而不是uarticle中的文章字段。
是否可以使用Mongoose和populate()来完成它,或者我应该做些什么呢?
谢谢,
答案 0 :(得分:15)
根据我在文档中检查的内容以及我从您那里听到的内容,这无法实现,但您可以在回调函数中自己填充“uarticle.article”文档。
但是我想指出另一个我认为更重要的方面。您在集合A中有文档引用集合B,在集合B的文档中,您有另外引用集合C中的文档。
你要么做错了(我指的是数据库结构),要么你应该在这里使用像MySQL这样的关系数据库。 MongoDB的强大之处在于您可以在文档中嵌入更多信息,因此必须进行较少的查询(将您的数据放在一个集合中)。虽然引用某些内容是可以的,但是有一个引用然后另一个引用似乎并不像你在这里充分利用了MongoDB。
也许您想分享您的情况和数据库结构,以便我们为您提供更多帮助。
答案 1 :(得分:2)
我遇到了同样的问题,但经过几个小时的努力,我找到了解决方案。它可以不使用任何外部插件:)
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);
}
答案 2 :(得分: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);
});
}
meta utils很粗糙...想要src?
答案 3 :(得分:0)
猫鼬v5.5.5似乎允许在已填充的文档上进行填充。
您甚至可以提供一个包含多个字段的数组以填充到填充的文档中!
var batch = await mstsBatchModel.findOne({_id: req.body.batchId})
.populate({path: 'loggedInUser', select: 'fname lname', model: 'userModel'})
.populate({path: 'invoiceIdArray', model: 'invoiceModel',
populate: [
{path: 'updatedBy', select: 'fname lname', model: 'userModel'},
{path: 'createdBy', select: 'fname lname', model: 'userModel'},
{path: 'aircraftId', select: 'tailNum', model: 'aircraftModel'}
]});
答案 4 :(得分:0)
或者您可以简单地将obj传递给填充对象:
const myFilterObj = {};
const populateObj = {
path: "parentFileds",
populate: {
path: "childFileds",
select: "childFiledsToSelect"
},
select: "parentFiledsToSelect"
};
Model.find(myFilterObj)
.populate(populateObj).exec((err, data) => console.log(data) );