如何在sequelize中实现此SQL QUERY(多个连接和多个AND / OR)

时间:2017-03-13 05:05:53

标签: javascript node.js postgresql sequelize.js

我一直在努力在续集中实现这一点(在SQL语句下面)一段时间没有运气。我最初不得不制作单独的续集查询来获取数据,但这只会带来许多限制。

    `SELECT "Documents".* FROM "Documents"
  INNER JOIN "AccessTypes"
    ON "AccessTypes"."id" = "Documents"."accessTypeId"
  INNER JOIN "Users"
    ON "Users"."id" = "Documents"."userId"
  INNER JOIN "Departments"
    ON "Departments"."id" = "Users"."departmentId"
  WHERE
    (("AccessTypes".name != 'private'
      AND "Departments"."id" = ${req.decoded.departmentId})
    OR "Users".id = ${req.decoded.id})
      AND ("Documents"."title" ILIKE '%${searchQuery}%'
        OR "Documents"."content" ILIKE '%${searchQuery}%'`

就我而言

    var dbQuery = {
    where: {
      $or: [
        {
          title: {
            $iLike: `%${searchQuery}%`
          }
        },
        {
          content: {
            $iLike: `%${searchQuery}%`
          }
        }
      ]
    },
    include: [{
      model: db.Users,
      where: { departmentId: req.decoded.departmentId }
    },
    {
      model: db.AccessTypes,
      where: { name: { $ne: 'private'}}
    }]
  };

  db.Documents.findAll(dbQuery)

我仍然需要根据提供的userId获取另一组文档。我觉得可行的方法是在'$或'语句中执行'Include'。但到目前为止,我的研究让我相信这是不可能的。

这是我的模特 访问类型

export default (sequelize, DataTypes) => {
  const AccessTypes = sequelize.define('AccessTypes', {
    name: {
      type: DataTypes.STRING,
      allowNull: false,
      isUnique: true
    }
  }, {
    classMethods: {
      associate: (models) => {
        // associations can be defined here
        AccessTypes.hasMany(models.Documents, {
          foreignKey: 'accessTypeId',
          onDelete: 'CASCADE'
        });
      }
    }
  });
  return AccessTypes;
};

用户

export default (sequelize, DataTypes) => {
const Users = sequelize.define('Users', {
    username: {
      type: DataTypes.STRING,
      unique: true,
      allowNull: false
    },
    firstname: {
      type: DataTypes.STRING,
      allowNull: false
    },
    lastname: {
      type: DataTypes.STRING,
      allowNull: false
    },
    email: {
      type: DataTypes.STRING,
      unique: true,
      allowNull: false,
      validate: {
        isEmail: true
      }
    },
    password: {
      type: DataTypes.STRING,
      allowNull: false
    },
    roleId: {
      type: DataTypes.INTEGER,
      allowNull: false,
      defaultValue: 3
    },
    departmentId: {
      type: DataTypes.INTEGER,
      allowNull: false
    }
  }, {
    classMethods: {
      associate: (models) => {
        // associations defined here
        Users.belongsTo(models.Roles, {
          onDelete: 'CASCADE',
          foreignKey: 'roleId'
        });
        Users.belongsTo(models.Departments, {
          onDelete: 'CASCADE',
          foreignKey: 'departmentId'
        });

        Users.hasMany(models.Documents, {
          as: 'documents',
          foreignKey: 'userId',
          onDelete: 'CASCADE'
        });
      }
    }, ...

部门

export default (sequelize, DataTypes) => {
  const Departments = sequelize.define('Departments', {
    name: {
      type: DataTypes.STRING,
      allowNull: false,
      isUnique: true
    }
  }, {
    classMethods: {
      associate: (models) => {
        // associations can be defined here
        Departments.hasMany(models.Users, {
          foreignKey: 'departmentId',
          onDelete: 'CASCADE'
        });
      }
    }
  });
  return Departments;
};

和文件

export default (sequelize, DataTypes) => {
  const Documents = sequelize.define('Documents', {
    title: {
      type: DataTypes.STRING,
      allowNull: false
    },
    content: {
      type: DataTypes.TEXT,
      allowNull: false
    },
    userId: {
      type: DataTypes.INTEGER,
      allowNull: false
    },
    accessTypeId: {
      type: DataTypes.INTEGER,
      allowNull: false,
      defaultValue: 1
    },
    docTypeId: {
      type: DataTypes.INTEGER,
      allowNull: false
    }
  }, {
    classMethods: {
      associate: (models) => {
        // associations can be defined here
        Documents.belongsTo(models.Users, {
          foreignKey: 'userId',
          as: 'user',
          onDelete: 'CASCADE'
        });
        Documents.belongsTo(models.DocumentTypes, {
          foreignKey: 'docTypeId',
          onDelete: 'CASCADE'
        });
        Documents.belongsTo(models.AccessTypes, {
          foreignKey: 'accessTypeId',
          onDelete: 'CASCADE'
        });
      }
    }
  });
  return Documents;
};

任何指针都将不胜感激 在此先感谢

1 个答案:

答案 0 :(得分:1)

这是一个相当复杂的查询(当然是Sequelize方式),所以你需要以不同的方式构建它。您应该使用sequelize.col()sequelize.where()sequelize.or()sequelize.and()等功能。此外,为了在查询中包含Departments模型,您需要在include查询的options对象中使用嵌套的findAll语句。您可以根据需要嵌套包含。

where: sequelize.and(
    sequelize.or(
        sequelize.and(
            sequelize.where(sequelize.col('AccessTypes.name'), '!=', 'private'),
            sequelize.where(sequelize.col('Departments.id'), '=', req.decoded.departmentId)
        ),
        sequelize.where(sequelize.col('Users.id'), '=', req.decoded.id)
    ),
    sequelize.or(
        { title: { $iLike: `%${searchQuery}%` } },
        { content: { $iLike: `%{searchQuery}%` } }
    )
),
include: [
    {
        model: db.Users,
        include: [ db.Departments ]
    },
    {
        model: db.AccessTypes
    }
]

您需要简要介绍上述功能的文档。简而言之,col()根据模型名称和字段创建正确的列选择,where()使用三个属性创建WHERE语句 - 列,条件(比较器)和逻辑,{{ 1}}创建or()语句,OR创建and()语句。 ANDor()都可以获得多个参数,允许您创建复杂的语句,就像您的一样。