【问题标题】:Sequelize: Create instance with existing associationSequelize:使用现有关联创建实例
【发布时间】:2021-10-04 20:30:01
【问题描述】:

试图让 sequelize 返回具有现有关联的新创建对象。我的目标是创建一个与现有组织相关联的新用户并返回两者。

user.model.js:

export default (sequelize, DataTypes) => {
  const User = sequelize.define('user', {
    email: {
      type: DataTypes.STRING,
      unique: true,
    },
  });
  User.associate = (models) => {
    User.belongsTo(models.Organisation, {
      foreignKey: {
        name: 'organisationId',
        field: 'organisation_id',
      },
    });
  };
  return User;
};

organisation.model.js:

export default (sequelize, DataTypes) => {
  const Organisation = sequelize.define('organisation', {
    name: {
      type: DataTypes.STRING,
      unique: true,
    },
  });
  return Organisation;
};

成功:获得现有用户

我可以使用查询的include 选项检索现有用户及其组织。

const user = models.User.findOne({
  where: {
    email: 'existing@user.com',
  },
  include: [
    { model: models.Organisation, attributes: ['name'] },
  ],
});

失败:创建新用户

实例已插入,但查询未能返回组织属性。

const user = models.User.create({
  email: 'new@user.com',
  organisationId: 'existing-organisation-id'
}, {
  include: [
    { model: models.Organisation, attributes: ['name'] },
  ],
});

成功:创建一个新用户并查询它

插入实例,然后使用通过组织数据检索到的另一个查询。问题是它需要对数据库进行两次查询。它应该只需要一个,

models.User.create({
  email: 'new@user.com',
  organisationId: 'existing-organisation-id'
}).then(() => {
  models.User.findOne({
    where: {
      email: 'new@user.com',
    },
    include: [
      { model: models.Organisation, attributes: ['name'] },
    ],
  });
});

我已经彻底阅读了这些文档,但我想我一定漏掉了一些东西。我要连接的数据库是 PostgreSQL。非常感谢有人指出我正确的方向。

【问题讨论】:

标签: sql node.js postgresql sequelize.js


【解决方案1】:

我认为目前还不支持:

options.include : 包含选项的数组 - 用于构建 预取/包含的模型实例

你可以同时使用include来创建一个关联的数据,但你不能就这样获取它

但更短的做法是:

models.User.create({
  email: 'new@user.com',
  organisationId: 'existing-organisation-id'
}).then((user) => {
    user.getOrganisation().then(org => {
        console.log(user,org); // <------ Check the console
    });
});

【讨论】:

  • 很遗憾没用,我只得到了当 promise 解决时返回的 idemailorganisationId 字段。
  • @nomadoda ,从包含中删除属性并重试。
  • 嗯不,抱歉,好像不影响结果。
  • 我也试过include: [models.Organisation]无济于事
  • 谢谢,很好用!我不确定我是否理解您提供的文档 - 这是否意味着它绝对不受支持?
【解决方案2】:

我发现的一件事是您在用户模型关系中使用organisation_id,但没有在模型中定义它。 Sequelize 将自动为没有定义 PK 的模型创建一个id 字段。至于它的字段名称,我不知道您的配置是如何设置的,如果它可以作为前缀或保留为id

当我定义关系时,我使用as 选项指定alias。我还指定了两个模型之间的关系。这是我的做法:

Organisation.hasMany(User, {
  as: 'members',
  foreignKey: '<FK field on User model>',
  sourceKey: '<PK field on Organisation model>' 
});

User.belongsTo(Organisation, {
  as: 'organisation',
  foreignKey: '<FK field on User model>',
  targetKey: '<PK field on Organisation model>'
});

当一个模型hasOne/hasMany其他模型时,options对象需要sourceKey prop(父模型的关键字段,通常是PK);当一个模型 belongsTo 另一个模型时,选项对象需要 targetKey 属性(与 sourceKey 相同)。 targetKey 和 sourceKey 只是指定关系:哪个模型是另一个的孩子或父母。

所以在你的情况下,我会这样做:

Organisation.hasMany(User, {
  as: 'members',
  foreignKey: 'organisation_id',
  name: 'organisationId',
  sourceKey: 'id' // assuming PK of Organisation is id
});

User.belongsTo(Organisation, {
  as: 'organisation',
  foreignKey: 'organisation_id', // assuming PK of Organisation is id
  name: 'organisationId',
  targetKey: 'id'
});

所以现在这样做应该可以了:

const user = models.User.create({
  email: 'new@user.com',
  organisationId: 'existing-organisation-id'
}, {
  include: [
    { association: models.Organisation, as: 'organisation', attributes: ['name'] },
  ],
});

当我开始学习它时,我一直在关注这个页面 - https://sequelize.org/master/manual/creating-with-associations.html

【讨论】:

    猜你喜欢
    • 2020-02-22
    • 2020-10-11
    • 1970-01-01
    • 1970-01-01
    • 2021-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多