Sequelize findall的每一个findall都可能吗?

时间:2014-06-26 21:28:39

标签: node.js sequelize.js

我有这张桌子。客户有项目和用户在项目中工作

Clients
- id
- name

Projects
- id
- name
- client_id

Users
- id
- name

UserProject
- user_id
- project_id

我尝试返回客户端的每个项目的所有用户,例如id = 1 最后的结果,像这样的JSON:

[{
   id:1
   name:"Project1"
   users:[{
            id:23
            name:"Robert Stark"
          },{
            id:67
            name: "John Snow"
          }]
 }, {
   id:2
   name:"Project2"
   users:[{
            id:1
            name:"Aria Stark"
          }]
}]

如果我发现项目工作正常

req.tables.Project.findAll({
    where: {
        client_id:1
    }
 }).success(function(projects) {
          ...

如果我找到项目的用户,那就可以了。

req.tables.UserProject.findAll({
   where: {
       project_id:1
   },
   include: [
       { model: req.tables.User, as: 'User' }
   ]
}).success(function(UsersProject) {
     ...

但是,我如何结合两个finAlls来返回每个项目中的所有用户?类似下一个代码的东西,但效果很好。我该怎么做? 我发现了这个:Node.js multiple Sequelize raw sql query sub queries但它对我不起作用或者我不知道如何使用它,因为我有2个循环而不仅仅是一个循环。我有项目循环和用户循环

req.tables.Project.findAll({
    where: {
        client_id:1
    }
}).success(function(projects) {

    var ret_projects=[];

    projects.forEach(function (project) {

         var ret_project={
             id:project.id,
             name:project.name,
             data:project.created,
             users:[]
         });

         req.tables.UserProject.findAll({
             where: {
                 project_id:project.id
             },
             include: [
                 { model: req.tables.User, as: 'User' }
             ]
         }).success(function(UsersProject) {

             var ret_users=[];

             UsersProject.forEach(function (UserProject) {
                 ret_users.push({
                     id:UserProject.user.id,
                     name:UserProject.user.name,
                     email:UserProject.user.email
                  });
             });
             ret_project.users=ret_users;
             ret_project.push(ret_project)
         });
     });

     res.json(projects);
});

3 个答案:

答案 0 :(得分:6)

听起来你已经有了解决方案,但我遇到了同样的问题并提出了这个解决方案。

非常类似于cvng所说的,只是使用嵌套的include。所以使用:

Project.belongsTo(Client);
Project.hasMany(User);
User.hasMany(Project);

然后:

req.tables.Client.find({
    where: { id:req.params.id },
    include: [{model: req.tables.Project, include : [req.tables.User]}]
  }).success(function(clientProjectUsers) {
    // Do something with clientProjectUsers.
    // Which has the client, its projects, and its users.
  });
}

能够加载进一步嵌套的相关模型'通过参数" option.include []来描述.include'在这里:Sequelize API Reference Model

将来可能会对其他人有用。

干杯!

答案 1 :(得分:2)

我认为您不必直接查询UserProject实体,而是使用Sequelize Eager加载方法来检索您的实体。

您的模型关联应如下所示:

Project.belongsTo(Client);
Project.hasMany(User, { as: 'Workers' });
User.hasMany(Project);

并且一旦您拥有与客户相关的所有项目,您的查找方法:

Project
     .findAll({ include: [{ model: User, as: 'Workers' })
     .success(function(users) {
         // do success things here
     }

看看http://sequelizejs.com/docs/1.7.8/models#eager-loading

希望它有所帮助!

答案 2 :(得分:0)

最后!!

cvng,你的例子很多,谢谢。 但我有3级客户端,项目,这是我的最终解决方案,这是一个很好的解决方案吗?

  req.tables.Client.find({
            where: { id:req.params.id },
            include: [{ model: req.tables.Project, as: 'Projects' }]
        }).success(function(client) {

            var ret ={
                    id:client.id,
                    name:client.name,
                    projects:[]
                };

            done = _.after(client.projects.length, function () {
                res.json(ret);
            });

            client.projects.forEach(function (project) {
                project.getUsers().success(function(users) {

                    var u=[]
                    users.forEach(function (user) {
                        u.push({
                            id:user.id,
                            name:user.name,
                        });
                    });

                    ret.projects.push({
                        id:project.id,
                        name:project.name,
                        users:u
                    });
                    done();

                });

            });

        });