【问题标题】:Sequelize hasMany Join associationSequelize hasMany 加入关联
【发布时间】:2022-01-23 01:56:53
【问题描述】:

我正在扩展我的应用程序,我需要加入我之前使用 Sequelize 创建的两个模型,它们如下:

用餐

sequelize.define('meal', {
    mealId: {
        type: DataTypes.INTEGER, 
        primaryKey: true,
        autoIncrement: true
    },
    quantity: {
        type: DataTypes.DECIMAL,
        allowNull: false
    },
    period: {
        type: DataTypes.INTEGER,
        allowNull: false
    }
})

食物

sequelize.define('food', {
    idFood: {
        type: DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true
    },
    nameFood: {
        type: DataTypes.STRING,
        allowNull: false
    }
})

我添加了如下关系:

db.food.hasMany(db.meal, {as : 'Food', foreignKey : 'idFood'});

这一行在 Meal 上添加了一个 idFood 列

快速解释发生了什么,Food 是一张包含许多食物(duh)的表格,例如面包、大米、豆类等。Meal 是一张表格,用于识别哪些食物用户选择的食物及其详细信息。

因此,我的理解是 Meal 有很多 Food(正如我之前添加的),但 Food 不需要与 Food 有任何关系strong>Meal,因为它只保存数据并且在我第一次填充它之后没有改变。但是当我尝试加入他们时:

db.meal.findAll({ include : [db.food] }).then(function (meals) {
    console.log(JSON.stringify(meals));
});

我收到以下错误:

Unhandled rejection Error: food is not associated to meal!

谁能解释我应该怎么做?我认为这与关系有关,但我在文档中找不到任何关于我应该做什么的好的解释。

谢谢!

编辑:阅读文档 (again),该示例很有意义,但我认为该示例不适用于我的情况,因为在他们的示例中,用户有一个任务,而任务属于用户。但就我而言,食物不属于餐食,因为许多餐食可以有不同数量的相同食物(或针对不同的用户)。

【问题讨论】:

    标签: node.js sqlite join sequelize.js relationships


    【解决方案1】:

    问题是必须以两种方式定义关系。目前,Sequelize 知道如何从 Food -> Meal 因为

    db.food.hasMany(db.meal, {as : 'Food', foreignKey : 'idFood'});
    

    但它不知道如何从膳食 -> 食物中获取。这就是为什么你必须反过来定义相同的关系,就像这样:

    db.meal.belongsTo(db.food, {foreignKey : 'idFood'});
    

    这不会添加任何 new 键,因为它会定义您在第一条语句中定义的 meal.idFood

    现在你应该可以执行了

    db.meal.findAll({ include : [db.food] }).then(function (meals) {
        console.log(JSON.stringify(meals)); <-- each array element of meals should have an attribute `food`
    });
    

    【讨论】:

    • 太棒了!这给了我想要的结果,只是最后一个问题。我正在打印 JSON.stringify(meals) 并且它显示了数据的每一部分,但是如果我想自己访问其中一些值怎么办?我做吗?
    • 喜欢访问每种食物吗?
    • 谢谢,我花了整整一天的时间才找到这个答案。
    【解决方案2】:

    如果您在关联中使用别名 ({ as: 'Food' }),您还需要在 include 语句中使用它。

    所以应该是这样的:

    db.meal.findAll({ 
      include : [{
        model: db.food,
        as: 'Food'
      }]
    }).then(function (meals) {
      console.log(JSON.stringify(meals));
    });
    

    如果关联有别名(使用 as 选项),则必须指定 包含模型时的此别名。请注意用户的工具如何别名为上面的仪器。为了做到这一点,您必须指定要加载的模型以及别名

    更多信息here

    【讨论】:

    • 仍然给我错误:未处理的拒绝错误:食物(食物)与用餐无关!
    • 阅读文档(再次),这个例子是有道理的,但我认为这个例子不适用于我的情况,因为在他们的例子中,用户有一个任务,任务属于用户.但就我而言,食物不属于一顿饭,因为许多膳食可以有不同数量的相同食物(或为不同的用户)。我怎样才能解决这个问题?
    • @leofontes 在你的情况下你需要实现多对多的关系,一顿饭可以有很多食物,一种食物可以用于多餐,所以这是有道理的。按照文档来实现这种关系。
    【解决方案3】:

    BelongsTo 还应该包含外键选项,其键与 hasMany 中的键相同

    Donor.hasMany(Donation, {
      foreignKey: "donorId",
      onDelete: "cascade",
    });
    Donation.belongsTo(Donor, { foreignKey: "donorId" });
    

    这对我有用

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多