简体   繁体   English

sequelize查询:响应给了我不存在的列

[英]sequelize querying: response gives me non-exist column

I'm creating small REST API in express.js using ORM sequelize. 我正在使用ORM sequelize在express.js中创建小型REST API。

I run into following issue: I would like to get all customers with their Photos. 我遇到了以下问题:我希望所有客户都能获得他们的照片。 I have two tables Customer and CustomerPhoto with 1:1 relation (so PrimaryKey is also Foreign key) 我有两个表Customer和CustomerPhoto与1:1的关系(所以PrimaryKey也是外键)

The problem is that sequelize would like to make a join with no exist column CustomerPhotoCustomerPhotoID . 问题是sequelize想要建立一个没有存在列CustomerPhotoCustomerPhotoID的连接 How Can I figure out? 我怎么能搞清楚? I ran into similar problem when I wanted all rows just only from customer table. 当我只想从客户表中获取所有行时,我遇到了类似的问题。 I "solved" it with attributes and retrieved only rows which I exactly needed. 我用属性 “解决”了它,只检索了我确切需要的行。

Customer.js model: Customer.js模型:

module.exports = (sequelize, DataTypes) => {
  const Customer = sequelize.define('Customer', {
    customerID: {
      type: DataTypes.INTEGER,
      allowNull: false,
      autoIncrement: true,
      primaryKey: true,
    },
    firstname: {
      type: DataTypes.STRING,
      validate: {
        len: [3, 10],
      },
    },
    lastname: {
      type: DataTypes.STRING,
      validate: {
        len: [3, 10],
      },
    },
    phone: {
      type: DataTypes.STRING,
    },
    email: {
      type: DataTypes.STRING,
      unique: true,
      validate: {
        isEmail: true,
      },
    },
  }, {
    classMethods: {
      associate(models) {
        Customer.hasOne(models.CustomerPhoto, { onDelete: 'cascade', hooks: 'true' });
        Customer.hasMany(models.Order, { onDelete: 'cascade', hooks: 'true' });
      },
    },
  });
  return Customer;
};

CustomerPhoto.js model: CustomerPhoto.js模型:

module.exports = (sequelize, DataTypes) => {
  const CustomerPhoto = sequelize.define('CustomerPhoto', {
    customerPhotoID: {
      allowNull: false,
      autoIncrement: true,
      primaryKey: true,
      type: DataTypes.INTEGER,
      references: {
        model: 'Customer',
        key: 'customerID',
        deferrable: sequelize.Deferrable.INITIALLY_IMMEDIATE,
      },
    },
    filename: {
      type: DataTypes.STRING,
      validate: {
        len: [3, 15],
      },
    },
    filetype: {
      type: DataTypes.BLOB,
    },
  }, {
    classMethods: {
      associate(models) {
        CustomerPhoto.hasOne(models.Customer, { onDelete: 'cascade', hooks: 'true' })
      },
    },
  })
  return CustomerPhoto
}


export function fetchCustomers(req, res) {
  models.Customer.findAll({
    attributes: ['firstname', 'lastname', 'phone', 'email', 'filetype'],
    include: [{
      model: models.CustomerPhoto,
      // if true inner join otherwise left join
      required: true,
    }],
  }).then((result) => {
    res.json(result)
  }).catch((error) => {
    res.send(error)
  })
}

I get following response in Postman: 我在邮递员中得到以下回复:

{
  "name": "SequelizeDatabaseError",
  "message": "column \"CustomerPhotoCustomerPhotoID\" does not exist",
  "parent": {
    "name": "error",
    "length": 128,
    "severity": "ERROR",
    "code": "42703",
    "position": "91",
    "file": "parse_relation.c",
    "line": "3183",
    "routine": "errorMissingColumn",
    "sql": "SELECT \"customerID\", \"firstname\", \"lastname\", \"phone\", \"email\", \"createdAt\", \"updatedAt\", \"CustomerPhotoCustomerPhotoID\", \"OrderOrderID\" FROM \"Customers\" AS \"Customer\" WHERE \"Customer\".\"customerID\" = '1';"
  },
  "original": {
    "name": "error",
    "length": 128,
    "severity": "ERROR",
    "code": "42703",
    "position": "91",
    "file": "parse_relation.c",
    "line": "3183",
    "routine": "errorMissingColumn",
    "sql": "SELECT \"customerID\", \"firstname\", \"lastname\", \"phone\", \"email\", \"createdAt\", \"updatedAt\", \"CustomerPhotoCustomerPhotoID\", \"OrderOrderID\" FROM \"Customers\" AS \"Customer\" WHERE \"Customer\".\"customerID\" = '1';"
  },
  "sql": "SELECT \"customerID\", \"firstname\", \"lastname\", \"phone\", \"email\", \"createdAt\", \"updatedAt\", \"CustomerPhotoCustomerPhotoID\", \"OrderOrderID\" FROM \"Customers\" AS \"Customer\" WHERE \"Customer\".\"customerID\" = '1';"
}

Ok There are some things around all here. 好的,这里有一些东西。 First of all, you don't need to declare the 1:1 relation on both models. 首先,您不需要在两个模型上声明1:1关系。 Just do it on one model and depends on how you do it. 只需在一个型号上进行,取决于您的操作方式。

You can use belongsTo or hasOne , both are use for 1:1 relations but work different. 您可以使用belongsTohasOne ,两者都用于1:1关系,但工作方式不同。

belongsTo create the foreign key on the origin model, and hasOne on the destination model. belongsTo在原型模型上创建外键,并在目标模型上创建hasOne。 Sequelize even recommend to use belongsTo on most of the cases. Sequelize甚至建议在大多数情况下使用belongsTo Here is the link. 是链接。

"Even though it is called a HasOne association, for most 1:1 relations you usually want the BelongsTo association since BelongsTo will add the foreignKey on the source where hasOne will add on the target." “即使它被称为HasOne关联,对于大多数1:1关系,你通常需要BelongsTo关联,因为BelongsTo会在源头上添加foreignKey,其中hasOne将添加到目标上。”

Now for your db schema, do you really need that the Primary key of CustomerPhoto has to be the foreign key refering Customer id Model? 现在对于您的数据库模式,您是否真的需要CustomerPhoto的主键必须是引用客户ID模型的外键? I recommend that you use regular primary key for CustomerPhotos and just make the reference on the Custommer Model that will create a column with the id association. 我建议您使用CustomerPhotos的常规主键,并在Custommer Model上创建一个将创建具有id关联的列的引用。

classMethods: {
      associate(models) {
        Customer.belongsTo(models.CustomerPhoto, { as : 'CustomerPhotoID', onDelete: 'cascade', hooks: 'true' });
        Customer.hasMany(models.Order, { onDelete: 'cascade', hooks: 'true' });
      },
    },

and on your query call the include like this: 并在您的查询调用包括这样:

models.Customer.findAll({
    attributes: ['firstname', 'lastname', 'phone', 'email', 'filetype'],
    include: [{
      model: models.CustomerPhoto,
      as : 'CustomerPhotoID',
      // if true inner join otherwise left join
      required: true,
    }],
  }).then

the "as" argumment will help sequelize find the relations sort of speaking. “as”argumment将帮助sequelize找到关系的一种说法。

@Ellebkey. @Ellebkey。 Thanks for your answer. 感谢您的回答。 Yes, I realized before your post that I did this mistake with hasOne association. 是的,我在你的帖子之前意识到我用hasOne关联做了这个错误。 I modified my code and use belongTo instead. 我修改了我的代码并改为使用belongsTo I also created foreign key in my Customer table but that didn't solve my problem. 我还在我的Customer表中创建了外键, 但这并没有解决我的问题。

The problem was in definition of my foreign key. 问题在于我的外键的定义。 Sequelize creates by default FK but I defined it by myself and didn't write it in association. Sequelize默认创建FK但我自己定义它并没有关联地编写它。

In the following example I decided to create customerPhotoID as FK in customer table. 在以下示例中,我决定在customer表中将customerPhotoID创建为FK。 After that I added it into association. 之后我将它添加到关联中。 And it works! 它的工作原理! It was really bullshit mistake. 这真的是胡说八道的错误。 I have to be more carefully next time. 下次我必须更加小心。

module.exports = (sequelize, DataTypes) => {
  const Customer = sequelize.define('Customer', {
    customerID: {
      allowNull: false,
      autoIncrement: true,
      primaryKey: true,
      type: DataTypes.INTEGER,
    },
    customerPhotoID: {
      type: DataTypes.INTEGER,
      references: {
        model: 'Customers',
        key: 'customerID',
        deferrable: sequelize.Deferrable.INITIALLY_IMMEDIATE,
      },
    },
    firstname: {
      type: DataTypes.STRING,
      validate: {
        len: [3, 10],
      },
    },
    lastname: {
      type: DataTypes.STRING,
      validate: {
        len: [3, 10],
      },
    },
    phone: {
      type: DataTypes.STRING,
    },
    email: {
      type: DataTypes.STRING,
      unique: true,
      validate: {
        isEmail: true,
      },
    },
  }, {
    classMethods: {
      associate(models) {
        Customer.belongsTo(models.CustomerPhoto, { foreignKey: 'customerPhotoID', onDelete: 'cascade', hooks: 'true' });
        Customer.hasMany(models.Order, { onDelete: 'cascade', hooks: 'true' });
      },
    },
  });
  return Customer;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM