Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node.js multiple Sequelize raw sql query sub queries

The title sounds complicated. I have a users table, and each user can have multiple interests. These interests are linked to the user via a lookup table. In PHP I queried the users table, then for each one did a query to find interests. How can I do this in Node.js/Sequelize? How can I set up some sort of promises too? For example:

sequelize.query("SELECT * FROM users").success(function(users) {
    for (var u in users) {
       sequelize.query("SELECT interests.id, interests.title FROM interests, user_interests WHERE interests.id = user_interests.interest_id AND user_interests.user_id = " + users[u].id).success(function(interests) {
       if (interests.length > 0) {
         users[u].interests = interests;
       }
    });
  }
  return users;
});
like image 332
Mark Robson Avatar asked Sep 05 '13 15:09

Mark Robson


1 Answers

From the return statement in the bottom of your code, it seems you have not totally grasped the asynchronous nature of node.js. The return statement in your code will be executed directly after the first call to sequelize.query, that is, before the query returns. This means that users will be undefined.

If you wanted to actually "return" the users and their interest, I would suggest something like this:

sequelize.query("SELECT * FROM users").success(function(users) {
    done = _.after(users.length, function () {
        callback(users)
    })

    for (var u in users) {
        sequelize.query("SELECT interests.id, interests.title FROM interests, user_interests WHERE interests.id = user_interests.interest_id AND user_interests.user_id = " + users[u].id).success(function(interests) {
            if (interests.length > 0) {
             users[u].interests = interests;
            }
            done();
        });
    }
});

In the code above _ refers to a utility lib. that executes the callback function after the function has been called users.length times. Callback is a function that is passed to your piece of code, and should process the return result, for example returning the users to the client in the context of a webserver.

Another comment - if you are only doing raw SQL queries, Sequelize might not be the best choice for you. Any reason why you are not using the SQL driver directly? If you want to use sequelize, you should take advantage of its features. Try to the define a model for users and interests, set up an association and load up users and interests in one go using JOINs / eager loading

update: An example using promises

sequelize.query("SELECT * FROM users").then(function(users) {
  return sequelize.Promise.map(users, function (u) {
    return sequelize.query("SELECT interests.id, interests.title FROM interests, user_interests WHERE interests.id = user_interests.interest_id AND user_interests.user_id = " + users[u].id).then(function(interests) {
      if (interests.length > 0) {
        user.interests = interests;
      }
    });
  });
});
like image 171
Jan Aagaard Meier Avatar answered Sep 26 '22 00:09

Jan Aagaard Meier