mongoose和人口嵌套

我已经读了一些关于mongoose的事情,就像它不能pipe理嵌套的人口一样。

事实是,当我做一个findOne()调用时,返回的对象能够使用填充函数。 但它似乎没有工作…

你能帮我处理一个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) ) ) 

编辑:

根据我们需要填写build筑物的地点(在代理)

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

Sitesché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 } } 

build筑模式:

 { 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 } } 

仅JavaScript响应。 你做翻译 🙂

在这种情况下,这实际上并没有真正的工作,但是为了做你想做的事情,你需要调用.populate()的“Model”forms:

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

尽pipe我使用了“async.waterfall” ,只是为了避免每次embedded式迭代的“缩进蠕变(indentation creep)”。

所以你可以看到实际上有必要以这种方式为每个特定的模型types调用.populate() 。 同样在“再次嵌套”“build筑”模型引用里面有必要的调用也需要在“该”文档被填充之后被调用。 所以这就是你之前提到的嵌套填充问题的一部分“调用堆栈”。

有了这么重的引用,你可能会考虑重新devise模式和/或embedded大量的这些数据。 它看起来很“关系”,因此你可能没有通过这种方式获得完整的MongoDB好处。

@Neil Lunn的回答是正确的,我只是想点亮一下你有兴趣清理你的代码:

 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)