2015-07-22 5 views
4

Я новичок в sails.js и использую "sails.js with Mongodb". У меня возникла проблема с глубокими ассоциациями, использующими populate в моем приложении sails.Глубокие ассоциации в парусах манго с использованием метода заполнения?

У меня есть отношения, как это:

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..!!'}); 
      } 
     } 
    }); 
} 

POSTMAN Запрос:

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

Как сделать глубокие вложенные ассоциации, используя населенные пункты? или Есть ли другой способ достичь этого?

Пожалуйста, может кто-нибудь помочь мне достичь этого.

Заранее спасибо.

ответ

2

Да, есть еще один способ сделать это.

Убедитесь, что вам нужен следующий модуль 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 для получения дополнительной документации.

3

В настоящее время это не поддерживается, но похоже, что the waterline team is working on it.

Если вы прочтете комментарии по этому вопросу, вы увидите, что есть an opened pull request на основе this gist.


Вы также можете сделать это вручную, но вы хотите получить много информации и асинхронный код может быстро стать очень грязным.

Есть много инструментов, которые помогут вам сохранить код читаемым:

Используйте с которыми вы чувствуете себя более комфортно. Существует пример использования обещаний и lodash в this answer. Я не буду предполагать, какие инструменты вы хотите использовать, но вы можете обновить вопрос, если вы все еще заблокированы позже.

Category имеет только одно отношение, в то время как Article имеет много. Я думаю, что в вашей ситуации вы должны загрузить категории без использования populate(). Затем вы можете зацикливать идентификаторы статей каждой категории, загружать каждую статью с populate() (или populateAll()) и переопределять category.Articles с результатом.


EDIT. Чтобы избежать ошибки Can\'t set headers after they are sent., вы можете использовать счетчик, чтобы отправить ответ только тогда, когда были выполнены все асинхронные функции. Вы в настоящее время отправляете ответ дважды.

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

Как только вы поймете, как работает асинхронный поток выполнения, вы должны улучшить код с помощью инструментов, упомянутых выше.

+0

Спасибо Alexis .. вручную, как я могу достичь этого .. вы можете показать мне часть кода. Это мне очень помогает. –

+0

Есть много вариантов, и сейчас у меня мало времени, но я попытался дать вам больше информации о том, как это сделать. –

+0

i переименован атрибут статьи из категории в качестве статей –

 Смежные вопросы

  • Нет связанных вопросов^_^