首页 文章

Sequelize:加入最大版本记录关联表?

提问于
浏览
1

在我的应用程序中,我有两个模型 useruserdetail . user detail只是一个包含唯一ID的表, userdetail(user_id, version) 上有一个唯一键 . 当我想获取最新的用户数据时,我运行SQL类似于以下内容:

SELECT userdetail1.password_hash FROM user
JOIN userdetail userdetail1 ON userdetail1.user_id = user.id
JOIN (
    SELECT user_id, MAX(version) version
    FROM userdetail
    GROUP BY user_id
) userdetail2 ON userdetail2.user_id = userdetail1.user_id AND userdetail2.version = userdetail1.version
WHERE user.id = 1;

我正在处理的数据库只允许INSERT,所以我只能通过在 userdetail 中插入一个新行来记录'update' .

我在Sequelize中定义了两个模型:

var UserDetail = sequelize.define('userdetail', {
    id: {
        type: DataTypes.INTEGER(10),
        allowNull: false,
        primaryKey: true,
        autoIncrement: true
    },
    user_id: {
        type: DataTypes.INTEGER(10),
        allowNull: false,
        references: {
            model: 'user',
            key: 'id'
        }
    },
    version: {
        type: DataTypes.INTEGER(10),
        allowNull: false
    },
    password_hash: {
        type: DataTypes.STRING,
        allowNull: false
    }
}, {
    timestamps: false,
    tableName: 'userdetail'
});
var User = sequelize.define('user', {
    id: {
        type: DataTypes.INTEGER(10),
        allowNull: false,
        primaryKey: true,
        autoIncrement: true
    },
    created: {
        type: DataTypes.DATE,
        defaultValue: DataTypes.NOW
    }
}, {
    timestamps: false,
    tableName: 'user'
});
User.hasMany(UserDetail.getModel(), {
    foreignKey: "user_id"
});
UserDetail.getModel().belongsTo(User, {
    foreignKey: "user_id"
});

我希望使用findAll()方法找到最新记录 . 这是我遇到问题的地方 . 我知道我需要加入三次(User < - > UserDetail < - > UserDetail),所以我有以下内容:

return this.model.findAll({
    include: [{
    model: this.UserDetail.getModel()
}, {
    model: this.UserDetail.getModel(),
    as: "userdetail2"
}]

但是,这会给出错误 userdetail (userdetail2) is not associated to user! ,所以我不确定如何两次加入同一个表?

此外,我需要第二个连接在其 ON 子句中的 userdetail.version 上有一个条件 - 这在Sequelize中是否可能?

3 回答

  • 1

    如果有人正在寻找答案,我在这个GitHub问题中回答了这个问题:https://github.com/sequelize/sequelize/issues/8600

    第一步是按照@Adam的建议两次声明一对多关联 .

    然后查询将如下所示:

    db.user.findAll({
      include: [
        {
          model: db.userDetail,
          required: false, // forces left join
          duplicating: false // prevents sub-queries
        },
        {
          model: db.userDetail,
          as: 'userdetail2',
          required: false, // forces left join
          duplicating: false, // prevents sub-queries
          on: {
            '$user.id$': { $col: 'user->userdetail2.userId' },
            '$user->userdetail.version$': { $col: 'user->userdetail2.version' }
          }
        }
      ],
      where: {
        '$user->membership_2.id$': { $eq: null }
      }
    });
    
  • 0

    你应该做两次关联:

    User.hasMany(UserDetail.getModel(), {
        foreignKey: "user_id"
    });
    User.hasMany(UserDetail.getModel(), {
        as: "userdetail2",
        foreignKey: "user_id"
    });
    UserDetail.getModel().belongsTo(User, {
        foreignKey: "user_id"
    });
    UserDetail.getModel().belongsTo(User, {
        as: "userdetail2",
        foreignKey: "user_id"
    });
    
  • 0

    上述答案的另一个变体:

    在文字语句中合并这是使用T-SQL . 这个想法是你加入但只有版本字段的最大结果 .

    db.user.findAll({
      include: [
        {
          model: db.userDetail,
          as: 'userdetail_a',
          where: {
           userId: userId,
           version: Sequelize.literal(' version = (
            Select MAX(version)
            FROM tbluserDetail 
            WHERE
            userId = [user].[userId])'),
          }
        }
      ],
    });
    

    你必须将'userdetail_a'的关联设置为hasOne,即使有很多,否则你的连接最终会成为数组中的一个值

相关问题