在风帆蒙戈使用填充方法的深度关联?

我是sails.js的新手,我正在使用“Mongodb的sails.js” 。 我在使用填充在我的风帆应用程序的深度关联有问题。

我有这样的关系:

Category has many to many relationship with Article. City has one to many relationship with Areas. Article has one to one relationship with City and Areas. 

Category.js

 module.exports = { schema: true, attributes: { //add referecnce to other article Articles: { collection: 'Article', via:'ref_category_id' }, category_name: { type:'string', required: true, unique: true }, } }; 

Article.js

 module.exports = { schema: true, attributes: { //adding reference to category ref_category_id: { collection:'Category', via:'Articles' }, //adding reference to city ref_city_id: { model:'City' }, //add a reference to area ref_area_id: { model:'Areas' }, //adding reference to tags tags: { collection: 'Tag', via:'articles' }, title:{ type:'string',required:true}, blurb: { type: 'string'}, description:{ type:'string'} } }; 

City.js

 module.exports = { schema: true, attributes: { Areas: { collection: 'Areas', via:'ref_city_id' }, ref_article_id:{ model:'Article' }, city_name: { type:'string', required:true, unique:true } } }; 

Areas.js

  module.exports = { schema: true, attributes: { area_name: { type:'string',required:true}, latitude: { type:'float'}, longitude: { type:'float'}, ref_city_id: { model: 'City' }, ref_article_id:{ model:'Article' } } }; 

Tag.js

  module.exports = { schema:false, attributes: { //adding reference to article articles: { collection: 'Article', via:'tags' }, tag_name:{type:'string', required:true, unique:true } } }; 

CategoryController.js

  searchCategory: function(req, res, next) { var category_name = req.param('category_name'); Category.find({category_name:{'like': '%'+category_name+'%'}}).populate('Articles').exec(function(err, category) { if(err) { return res.json({'status':486,'status_message':'Server Error'}); } else { if(category.length > 0) { var c = parseInt(category[0].Articles.length,10); console.log(c); var i = parseInt('0',10); for (i=0; i<c; i++) { console.log('i value in loop = ' + i); Article.find({id:category[0].Article[i].id}).populateAll().exec(function(err,article_info) { if(err) { return res.send(err); } else { console.log(article_info); console.log('-------------------------------------------'); res.json(article_info); console.log(' I value = ' + i); } }); } //console.log(category); //return res.json({'status':479,'status_message':'Success..!!','category_info':category}); } else { return res.json({'status':489,'status_message':'failure..!! No categories found..!!'}); } } }); } 

邮递员要求:

  http://localhost:1337/category/searchCategory {"category_name":"travel"} 

这是我的JSON响应:在这里,我只获得与类别映射的文章。 但我想显示映射到文章的城市,地区和标签的值。

  { "status": 479, "status_message": "Success..!!", "category_info": [ { "Articles": [ { "ref_city_id": "55a766d0a29811e875cb96a1", "ref_area_id": "55a78b69578393e0049dec43", "title": "title", "blurb": "blurb", "description": "Description", "createdAt": "2015-07-16T12:36:36.778Z", "updatedAt": "2015-07-16T12:48:20.609Z", "id": "55a7a55439ace79e0512269d" }, ], "category_name": "Cooking ", "id": "55a6b26aee9b41de747547bb", "createdAt": "2015-07-15T19:20:10.670Z", "updatedAt": "2015-07-15T19:20:10.670Z" } ] } 

如何使用填充来完成深度嵌套关联? 或者有什么其他的方式来实现呢?

请任何人都可以帮助我做到这一点。

提前致谢。

是的,还有另一种方法可以做到这一点。

确保你需要下面的npm模块。

 var nestedPop = require('nested-pop'); 

 searchCategory: function(req, res, next) { var category_name = req.param('category_name'); Category.find({category_name:{'like': '%'+category_name+'%'}}) .populate('Articles') .exec(function(err, category) { if(err) return res.json({'status':486,'status_message':'Server Error'}); if(category.length > 0) { var c = parseInt(category[0].Articles.length,10); console.log(c); var i = parseInt('0',10); for (var i = 0; i < c; i++) { console.log('i value in loop = ' + i); Article.find({id:category[0].Article[i].id}) .populateAll() .exec(function(err, article_info) { if(err) return res.send(err); return nestedPop(article_info, { ref_city_id: { as: 'City', populate: [ 'things', 'you', 'want', 'to', 'populate', 'for', 'city' ], }, ref_area_id: { as: 'Area', // or Areas (whatever the model name is) populate: [ 'things', 'you', 'want', 'to', 'populate', 'for', 'area' ] } }).then(function(article_info) { console.log(article_info); console.log('------------------------------------------'); res.json(article_info); console.log(' I value = ' + i); }); }); } } else { return res.json({'status':489,'status_message':'failure..!! No categories found..!!'}); } }); } 

请访问https://www.npmjs.com/package/nested-pop获取更多文档&#x3002;

目前尚未得到支持,但似乎水线队正在开展工作 。

如果您阅读了关于这个问题的评论,您将会看到基于这个要点已经有一个拉开的请求 。


您也可以手动执行,但是您想要检索许多信息, 并且asynchronous代码可能会很快变得非常混乱

有很多工具可以帮助你保持代码的可读性:

  • 命名callback函数
  • promises (已在Waterline中提供 )
  • asynchronous
  • lodash

使用你觉得更舒适的。 在这个答案中有一个使用promise和lodash的例子。 我不会假定你想使用哪种工具,但如果你以后仍然被阻止你可以更新这个问题

Category只有一个关系,而Article有很多 。 我认为在你的情况下,你应该加载的类别不使用populate() 。 然后你可以循环投掷每个类别的文章id,加载每个文章与populate() (或populateAll() )和覆盖category.Articles与结果。


编辑 。 避免Can\'t set headers after they are sent. 错误,只有在执行完所有asynchronousfunction后,才能使用计数器来确保发送响应。 您目前正在发送回复两次。

 var articles = []; var cpt = 0; for (i=0; i<c; i++) { Article.find({id:category[0].Article[i].id}).populate('ref_category_id').populate('tags').populate('ref_city_id').populate('ref_area_id').exec(function(err,article_info) { // Simplified callback function cpt++; // Increment every time the callback function is executed articles.push(article_info); if (cpt === c) { // We should have "c" executions of the callback function before sending the result in the response // This is working if `category` is an instance of `Category`, // but in your controller, `category` contains an array of `Category`. // Do you want to return a single Category or should you rename `category` into `categories` ? category.Articles = articles; res.json(category); } }); } 

一旦你明白asynchronous执行stream程是如何工作的,你应该使用上面提到的工具来改进代码。