Pisix
Pisix

Reputation: 205

Populate model of the model with sails js

I'm trying to populate model of the model with sails unfortunally it doesn't work.

I have 3 models

/**
  Conversation.js

**/
module.exports = {

    autoCreatedAt: false,
    autoUpdatedAt: false,
    tableName:'conversation',
    attributes: {
        idConversation:{
            columnName:'IDCONVERSATION',
            primaryKey:true,
            autoIncrement:true,
            unique:true,
            type:'integer',
            index:true
        },
        dateStartConversation:{
          columnName:'DATEDEBUT',
          type:'date',
          index:true
        },
        user1:{
            columnName:'IDUSER1',
            model:'user',
            notNull:true
        },
        user2:{
            columnName:'IDUSER2',
            model:'user',
            notNull:true
        },
        article:
        {
          model:'article',
          columnName:'IDARTICLE',
          notNull:true
        }
    }
};



/**
   Article.js
**/
module.exports = {
    autoPK: false,
    autoCreatedAt: false,
    autoUpdatedAt: false,
    tableName:'article',
    attributes: {
        idArticle:{
            type:'integer',
            unique:true,
            columnName:'IDARTICLE',
            autoIncrement:true,
            primaryKey:true
        },
        title:{
            type:'string',
            required:true,
            columnName:'TITRE',
            index:true,
            notNull:true
        },
        utilisateur:{
            model:'utilisateur',
            columnName:'IDUTILISATEUR',
            required:true,
            notNull:true,
            dominant:true
        },
        images:{
            collection:'image',
            via:'article'
        },

        conversation:{
          collection:'conversation',
          via:'article'
        }
    }
};

/**
   Image.js
**/
module.exports = {
    autoCreatedAt: false,
    autoUpdatedAt: false,
    tableName:'image',
    attributes: {
        idImage:{
            columnName:'IDIMAGE',
            primaryKey:true,
            autoIncrement:true,
            unique:true,
            type:'integer'
        },
        pathImage:{
            columnName:'PATHIMAGE',
            required:true,
            type:'string',
            notNull:true
        },
        article:{
            model:'article',
            columnName:'IDARTICLE',
            notNull:true,
            dominant:true

        }
    }
};

As you can see in my model, an conversation its between Two user, about one article, and those article cas have one or many Images.

So I want to get all conversations of one user and I able to populate with article but I'm not able to populate article with Image below how I proceed

 Conversation.find().populate('article').populate('user1').populate('user2').where({
      or : [
        { user1: iduser },
        { user2: iduser }
      ]})
    .then(function( conversations) {
        var i=0;
        conversations.forEach(function(element,index){
          i++;
          console.log("article "+index+" "+JSON.stringify(element.article));
          Article.findOne({
            idArticle:element.article.idArticle
          }).populate('images').then(function(newArticle){
            //I  try to set article with the newArticle but it don't work
            element.article=newArticle;
          })
          if(i==conversations.length){

            res.json({
              hasConversation:true,
              conversation:conversations
            });
          }
        });

    })

Because deep populate is not possible using sails, I try to use a loop to populate each article with associate Images and set it in conversation, But article is never set in conversation.

How can I fix it ?

Upvotes: 3

Views: 418

Answers (2)

sgress454
sgress454

Reputation: 24958

Judging by the if(i==conversations.length) at the end, you seem to have an inkling that you need to write asynchronous code. But you're iterating i inside of the synchronous forEach loop, so your response is happening before any of the database queries even run. Move the i++ and the if inside of the callback for Article.findOne:

 Conversation.find().populate('article').populate('user1').populate('user2').where({
      or : [
        { user1: iduser },
        { user2: iduser }
      ]})
    .then(function( conversations) {
        var i=0;
        conversations.forEach(function(element,index){
          console.log("article "+index+" "+JSON.stringify(element.article));
          Article.findOne({
            idArticle:element.article.idArticle
          }).populate('images').then(function(newArticle){
            // Associate the article with the conversation,
            // calling `toObject` on it first
            element.article= newArticle.toObject();
            // Done processing this conversation
            i++;
            // If we're done processing ALL of the conversations, send the response
            if(i==conversations.length){
              res.json({
                hasConversation:true,
                conversation:conversations
              });
            }

          })
        });

    })

You'll also need to call toObject on the newArticle instance before assigning it to the conversation, because it contains getters and setters on the images property which behave unexpectedly when copied.

I'd also recommend refactoring this to use async.each, which will make it more readable.

Upvotes: 2

Dinana
Dinana

Reputation: 300

Until this is resolved (https://github.com/balderdashy/sails-mongo/issues/108), you can use this function that I developed to solve this: https://gist.github.com/dinana/52453ecb00d469bb7f12

Upvotes: 1

Related Questions