node.js - Sequelize 模型 - 删除 belongsToMany n :m association 的项目

标签 node.js postgresql sequelize.js

我正在尝试为我的应用程序设置一个 DELETE 路由,它使用带有 Postgres 数据库的 Sequelize。我有两个不同的模型,“产品”和“兴趣”(将兴趣视为一种类别或标签)。 Products can have multiple Interests and Interests can have multiple Products,所以我使用的是belongsToMany关联。因此,我有三个表:ProductsInterestsProductInterests。以下是我如何设置关联:

对于产品:

Product.belongsToMany(models.Interest, {
    foreignKey: 'productId',
    through: models.ProductInterest,
    as: 'interests',
    onDelete: 'CASCADE',
    hooks: true
});

对于兴趣:

Interest.belongsToMany(models.Product, {
    through: models.ProductInterest,
    as: 'products',
    foreignKey: 'interestId',
    onDelete: 'CASCADE',
    hooks: true
});

这是在我的产品 Controller 中调用的方法:

destroy(req, res) {
    return Product
        .findById(req.params.productId, {
            include: [
                {
                    association: Product.associations.interests
                }
            ]
        })
        .then((product) => {
            if (!product) {
                return res.status(404).send({
                    message: 'Product not found'
                });
            }
            return product
                .destroy()
                // I've also tried the following:
                // .destroy({
                //    truncate: true,
                //    cascade: true
                // })
                .then(() => res.status(204).send())
                .catch(error => res.status(400).send(error));
        })
        .catch(error => res.status(400).send(error));

这会导致无限循环,并记录这些查询:

Executing (default): SELECT "Product"."id", "Product"."title", "Product"."brand", "Product"."url", "Product"."imageUrl", "Product"."currentPrice", "Product"."male", "Product"."female", "Product"."asin", "Product"."storeName", "Product"."createdAt", "Product"."updatedAt", "ProductInterest"."createdAt" AS "ProductInterest.createdAt", "ProductInterest"."updatedAt" AS "ProductInterest.updatedAt", "ProductInterest"."interestId" AS "ProductInterest.interestId", "ProductInterest"."productId" AS "ProductInterest.productId" FROM "Products" AS "Product" INNER JOIN "ProductInterests" AS "ProductInterest" ON "Product"."id" = "ProductInterest"."productId" AND "ProductInterest"."interestId" = 1;
Executing (default): SELECT "Interest"."id", "Interest"."name", "Interest"."createdAt", "Interest"."updatedAt", "ProductInterest"."createdAt" AS "ProductInterest.createdAt", "ProductInterest"."updatedAt" AS "ProductInterest.updatedAt", "ProductInterest"."interestId" AS "ProductInterest.interestId", "ProductInterest"."productId" AS "ProductInterest.productId" FROM "Interests" AS "Interest" INNER JOIN "ProductInterests" AS "ProductInterest" ON "Interest"."id" = "ProductInterest"."interestId" AND "ProductInterest"."productId" = 6;

我的意图是 a) 删除 Product 表中的产品; b) 删除 ProductInterest 表中的关联记录。如果正在删除产品,我不希望删除兴趣本身。同样,如果兴趣被删除(只是关联),我不希望删除关联的产品。

我已经围绕这个尝试了几种不同的排列,但找不到正确的方法。任何帮助将不胜感激。

更新

稍微调试一下 sequelize 代码让我认为我不应该那样使用 cascade。它基本上是在尝试删除产品,然后(由于级联)尝试删除兴趣(我不想要),然后(由于级联)尝试删除相关产品,等等。仍然不确定是什么正确的解决方案是。

最佳答案

首先,belongsToMany 的默认行为是删除它的级联,写在 DOCS 中。

For 1:1 and 1:m associations the default option is SET NULL for deletion, and CASCADE for updates. For n:m, the default for both is CASCADE. This means, that if you delete or update a row from one side of an n:m association, all the rows in the join table referencing that row will also be deleted or updated.

但我认为在创建表创建或迁移中创建外键引用时明确编写它是行不通的,如下所示:

queryInterface.createTable('ProductInterest', {
  productId: {
    type: Sequelize.INTEGER,
    references: {
        model: 'Product',
        key: '_id',
      },
    onDelete: 'cascade'
  },
  interestId: {
    type: Sequelize.INTEGER,
    references: {
        model: 'Interest',
        key: '_id',
      },
    onDelete: 'cascade'
  },
});

关于node.js - Sequelize 模型 - 删除 belongsToMany n :m association 的项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41851839/

相关文章:

sql - Postgresql 解释计划差异

mysql - 将记录从 MySql 迁移到 Postgres 时,如何在 Rails 中设置查询的默认时区或设置日期时间值的偏移量

node.js - Sequelize、findAll、属性不能重命名列

node.js - 防止 Sequelize 在执行查询时将 SQL 输出到控制台?

javascript - 如何将种子值传递给 Sequelize 中的随机顺序函数

node.js - BinaryJS 服务器响应

node.js - 将在任何路由上执行的自定义中间件

node.js - 判断预保存回调中是否有记录 "is new"

javascript - Node.js:使用 Bluebird 将模块函数从回调转换为 Promise

macos - 安装最新版本的 OS X(Yosemite 或 El Capitan)后缺少 `pg_tblspc`