Mongoose:填充填充字段
Posted
技术标签:
【中文标题】Mongoose:填充填充字段【英文标题】:Mongoose: Populate a populated field 【发布时间】:2012-01-22 13:21:42 【问题描述】:我使用 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 的“article”字段(“uarticle”)。
但是,使用此代码,Mongoose 仅使用 UserArticle 模型填充“uarticle”,而不是 uarticle 内部的文章字段。
是否可以使用 Mongoose 和 populate() 来完成它,或者我应该做其他事情?
谢谢,
【问题讨论】:
我遇到了同样的问题,其中引用嵌入在数组中 -> myList: [ mid: type:Schema.ObjectId, 'ref':'OtherModel', meta: [细绳]]。当我尝试 .populate('myList.mid')... TypeError: Cannot call method 'path' of undefined 时,这会产生以下错误 【参考方案1】:根据我在文档中查看的内容以及从您那里听到的信息,这无法实现,但您可以在回调函数中自己填充“uarticle.article”文档。
但是我想指出另一个我认为更重要的方面。您在集合 A 中有引用集合 B 的文档,在集合 B 的文档中,您有另一个对集合 C 中文档的引用。
你要么做错了(我指的是数据库结构),要么你应该在这里使用关系数据库,比如 mysql。 MongoDB 的强大之处在于您可以在文档中嵌入更多信息,因此必须进行较少的查询(将数据放在单个集合中)。虽然引用某些东西是可以的,但有一个引用然后另一个引用似乎并没有在这里充分利用 MongoDB。
也许您想分享您的情况和数据库结构,以便我们为您提供更多帮助。
【讨论】:
Logs 集合是唯一一个有奇怪引用的集合,我只是想要,因为其他集合只有 1 个引用(以避免重复很多次相同的数据)。我认为为了避免使用大量信息,我不会填充“uarticle”,客户端会请求获取文章的详细信息,只是为了让事情变得简单快捷。 您能否就您的答案提供更多详细信息——我是否没看错,甚至应该检查一个参考。我刚刚开始使用 mongodb。毕竟很多关系表只有一个外键。嵌入文档是否比填充 ObjectId 引用更可取? 这真的取决于项目的结构,有时您甚至可能想要复制数据(嵌入)以提高速度,有时您可能需要引用它,因为该数据将仅在某些条件。【参考方案2】:怎么样:
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】:您可以使用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
)
)
免责声明:我是插件的作者。
【讨论】:
【参考方案4】:我遇到了同样的问题,但经过几个小时的努力我找到了解决方案。它可以不使用任何外部插件:)
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);
【讨论】:
【参考方案5】:Mongoose 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'
]);
【讨论】:
【参考方案6】:或者您可以简单地将 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) );
【讨论】:
以上是关于Mongoose:填充填充字段的主要内容,如果未能解决你的问题,请参考以下文章