我已经阅读了一些关于Mongoose的内容,因为它无法管理嵌套群体。
事实是,当我执行findOne()调用时,返回的对象能够使用populate函数。但它似乎没有工作......
你能帮我处理2级填充吗?多个查询不是问题。
这是我的CoffeeScript代码:
Agency.findOne({"agencyUsers": idUser}, '_id agencyUsers agencySites agencyDevices').populate([
{path: 'agencyUsers', match: { actif: true}, select: '_id userPin'},
{path: 'agencySites', match: { actif: true}, select: '_id siteName siteBuildings siteSectors siteUsers'},
{path: 'agencyDevices', match: { actif: true}, select: '_id deviceMac'}
])
.exec((err, res)=>
if err
deffered.reject err
else
res.populate('agencySites.siteBuildings', (errs, ress)=>
deffered.resolve(res)
)
)
编辑:
根据我们需要在站点(代理商)中填充建筑物的事实
AgencySchema:
{
agencyName: String,
agencyStreet: String,
agencyCity: String,
agencyPostal: String,
agencyCountry: String,
agencyPhone: String,
agencyFax: String,
agencyMail: String,
agencySiret: String,
agencyAgencies: [
{ type: Schema.ObjectId, ref: 'Agency' }
],
agencyDevices: [
{ type: Schema.ObjectId, ref: 'Device' }
],
agencySites: [
{ type: Schema.ObjectId, ref: 'Site' }
],
agencyUsers: [
{ type: Schema.ObjectId, ref: 'User' }
],
agencyModules: [
{ type: Schema.ObjectId, ref: 'Module' }
],
actif: {type: Boolean, default: true},
actif_date: { type: Date, default: null },
creation_date: { type: Date, default: Date.now },
edit_date: { type: Date, default: null }
}
网站schéma:
{
siteName: String,
siteStreet: String,
siteCity: String,
sitePostal: String,
siteCountry: String,
sitePhone: String,
siteMail: String,
siteAgencies: [
{ type: Schema.ObjectId, ref: 'Agency' }
],
siteUsers: [
{ type: Schema.ObjectId, ref: 'User' }
],
siteSectors: [
{ type: Schema.ObjectId, ref: 'Sector' }
],
siteBuildings: [
{ type: Schema.ObjectId, ref: 'Building' }
],
siteModules: [
{ type: Schema.ObjectId, ref: 'Module' }
],
actif: {type: Boolean, default: true},
actif_date: { type: Date, default: null },
creation_date: { type: Date, default: Date.now },
edit_date: { type: Date, default: null }
}
建筑架构:
{
buildingName: String,
buildingFloors: [
{ type: Schema.ObjectId, ref: 'Floor' }
],
actif: {type: Boolean, default: true},
actif_date: { type: Date, default: null },
creation_date: { type: Date, default: Date.now },
edit_date: { type: Date, default: null }
}
答案 0 :(得分:1)
仅限JavaScript响应。你执行translation:)
在这种情况下,这并没有真正起作用,因为实际上这些原因让我感到懊恼,但为了做你想做的事,你需要打电话给"模型"形式为.populate()
而不是:
Agency.findOne({"agencyUsers": idUser}, '_id agencyUsers agencySites agencyDevices')
.populate([
{ "path": "agencyUsers", "match": { "actif": true}, "select": "_id userPin" },
{
"path": "agencySites",
"match": { "actif": true },
"select": "_id siteName siteBuildings siteSectors siteUsers"
},
{
"path": "agencyDevices",
"match": { "actif": true},
"select": "_id deviceMac"
}
]).exec(function(err,doc) {
if (err) {
deffered.reject(err);
} else {
async.waterfall([
function(callback) {
Agency.populate( doc, { "path": "agencyAgencies.siteAgencies" },callback);
},
function(doc,callback) {
User.populate( doc, { "path": "agencyAgencies.siteUsers" },callback);
},
function(doc,callback) {
Sector.populate( doc, { "path": "agencyAgencies.siteSectors" },callback);
},
function(doc,callback) {
Building.populate( doc, { "path": "agencyAgencies.siteBuildings" },callback);
},
function(doc,callback) {
Module.populate( doc, { "path": { "agencyAgencies.siteModules" },callback);
}
],function(err,res) {
if (err) {
deffered.reject(err);
} else {
Floor.populate(res,{ "path": "agencyAgencies.siteBuildings.buildingFloors" },function(err,res) {
if (err) {
deffered.reject(err);
} else {
deffered.resolve(res);
}
});
}
});
}
});
尽管我使用"async.waterfall",但只是试图避免"缩进蠕变"每次嵌入式迭代。
因此,您可以看到实际上有必要以这种方式为每种特定的模型类型调用.populate()
。还有一个必要的呼叫在"再次嵌套" "建筑"模型参考也需要在""之后调用。文档已填充。所以它就是"调用堆栈"这是你之前提到的嵌套填充问题的一部分。
通过如此繁重的引用,您可以考虑重新设计架构和/或嵌入大量此类数据。它看起来非常"关系"因此,你可能不会通过这种方式获得完整的MongoDB好处。
答案 1 :(得分:1)
@Neil Lunn的回答是正确的,我只想对co有所了解,因为你有兴趣清理你的代码:
co(function* {
var agency = yield Agency.findOne({'agencyUsers': idUser}, '_id agencyUsers agencySites agencyDevices')
.populate(
{ 'path': 'agencyUsers', 'match': { 'actif': true }, 'select': '_id userPin' },
{ 'path': 'agencySites', 'match': { 'actif': true }, 'select': '_id siteName siteBuildings siteSectors siteUsers' },
{ 'path': 'agencyDevices', 'match': { 'actif': true }, 'select': '_id deviceMac' })
agency = yield Agency.populate(agency, 'agencyAgencies.siteAgencies')
agency = yield User.populate(agency, 'agencyAgencies.siteUsers')
agency = yield Sector.populate(agency, 'agencyAgencies.siteSectors')
agency = yield Building.populate(agency, 'agencyAgencies.siteBuildings')
agency = yield Module.populate(agency, 'agencyAgencies.siteModules')
return agency
})
.then(agency => {
Floor.populate(agency, 'agencyAgencies.siteBuildings.buildingFloors', function (err, res) {
if (err)
deferred.reject(err)
deferred.resolve(agency)
})
})
.catch(deferred.reject)
答案 2 :(得分:1)
从版本^ 4.1.x开始,深层人口实际上是猫鼬中的事物,因此执行类似操作是有效的:-
Post.find({}).populate({
path: 'user',
select: 'id name',
populate: {
path: 'friends',
select: 'id name,'
populate: {
path: 'friends',
select: 'id name',
}
}
})
populate
可以将一个对象或对象数组作为值,这意味着您可以填充引用不同集合的兄弟属性。
有关更多信息,请查看此帖子:http://frontendcollisionblog.com/mongodb/2016/01/24/mongoose-populate.html