Sequelize M:N 关联不是通过 table 记录创建的

Sequelize M:N association not creating through table record

当我使用 through 选项创建带有关联标签的食谱时,在我连接的 mysql 数据库中的连接 table 中没有创建任何记录。

这是我的模型定义:

export const Recipe = sequelize.define('Recipe', {
    // Model attributes are defined here
    title: {
        type: DataTypes.STRING,
        allowNull: false
    },
    image: {
        type: DataTypes.STRING,
        allowNull: true
    },
    prepTime: {
        type: DataTypes.DOUBLE,
        allowNull: false
    },
    cookTime: {
        type: DataTypes.DOUBLE,
        allowNull: false
    },
    totalTime: {
        type: DataTypes.DOUBLE,
        allowNull: false
    },
    servings: {
        type: DataTypes.INTEGER,
        allowNull: false
    },
    rating: {
        type: DataTypes.INTEGER,
        allowNull: false
    },
    notes: {
        type: DataTypes.STRING, allowNull: true
    },
}, {
    // Other model options go here
    tableName: 'Recipes'
});

export const Tag = sequelize.define('Tag', {
    // Model attributes are defined here
    name: {
        type: DataTypes.STRING,
        allowNull: false
    },
}, {
    // Other model options go here
    tableName: 'Tags'
});

export const RecipeTag = sequelize.define('RecipeTag', {
    // Model attributes are defined here
}, {
    // Other model options go here
    timestamps: false,
    tableName: 'RecipeTags'
});

这是我的联想:

Recipe.belongsToMany(Tag, {
    through: RecipeTag,
    foreignKey: 'recipeId',
    as: 'tags'
})

Tag.belongsToMany(Recipe, {
    through: RecipeTag,
    foreignKey: 'tagId',
    as: 'recipes'
})

这是创建调用:

Recipe.create(args, {
                model: Tag,
                through: RecipeTag,
                as: 'tags'
            });

这是数据:

{
  "title": "Test Recipe",
  "image": "test",
  "prepTime": 20,
  "cookTime": 40,
  "totalTime": 60,
  "servings": 2,
  "rating": 5,
  "categoryId": 1,
  "tags": [
    {
      "name": "New tag",
      "id": 1
    }
  ],
}

使用此设置,创建方法仅创建一个新配方。如何在创建新食谱的同时使用 create 方法将记录添加到加入的 RecipeTags table?我已经设法通过做这样的事情来让它工作:

args.tags.map(async (tag: { tagId: number }) => {
    await RecipeTag.create({tagId: tag.tagId, recipeId: recipe.id})
});

但如果可能的话,我宁愿在创建时完成它。

您需要用 include 包裹关联选项。

Recipe.create(args, {
    include: {
        model: Tag,
        through: RecipeTag,
        as: 'tags'
    }
});

更新:

为了防止重复,可以添加ignoreDuplicates选项,数据必须包含主键值。

{
  "title": "Test Recipe",
  ...
  "tags": [
    {
      "name": "New tag",
      "id": 1   # this is important
    }
  ]
}

然后

Recipe.create(args, {
    include: {
        model: Tag,
        through: RecipeTag,
        as: 'tags',
        ignoreDuplicates: true  // Add this
    }
});

这个选项有一些错误,如果你最近没有更新,我建议你使用更新版本的 Sequelize。