aks*_*ade 24 node.js express sequelize.js
我们如何在sequelize orm中实现像bulkCreate这样的bulkUpdate,我搜索了sequelize的整个文档但没有找到与bulkUpdate相关的任何内容,所以我尝试在for循环中循环更新,它可以工作,但是还有其他方法可以批量更新
Sak*_*vam 41
使用bulkCreate 到bulkUpdate 方法。
bulkCreate([...], { updateOnDuplicate: ["name"] })
Run Code Online (Sandbox Code Playgroud)
updateOnDuplicate
是一个字段数组,当主键(或可能是唯一键)与行匹配时将更新这些字段。确保您的模型和dataArray
两者中至少有一个唯一字段(比如 id)用于 upsert。
参考这里
Ole*_*rin 20
你可以,如果你想用相同的值更新很多记录!示例:我想一次更新 10 个用户的字段“activationStatus”,1 个用户 = 数据库中的 1 个记录,并且我有用户 ID 数组,然后:
User.update({ activationStatus: 'active'}, {
where: {
id: [1,2,3,4,5,6,7,8,9,10]
}
});
Run Code Online (Sandbox Code Playgroud)
它将类似于 SQL 查询:
UPDATE User SET activationStatus = 'active' WHERE id IN(1,2,3,4,5,6,7,8,9,10);
Run Code Online (Sandbox Code Playgroud)
您可以在此处找到有关 Sequelize 运算符别名的更多信息
最小bulkCreate
+updateOnDuplicate
示例
只是为了澄清/sf/answers/3843044761/中提到的内容
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
});
(async () => {
const Integer = sequelize.define('Integer',
{
value: {
type: DataTypes.INTEGER,
unique: true, // mandatory
primaryKey: true,
},
name: {
type: DataTypes.STRING,
},
inverse: {
type: DataTypes.INTEGER,
},
},
{
timestamps: false,
}
);
await Integer.sync({force: true})
await Integer.create({value: 2, inverse: -2, name: 'two'});
await Integer.create({value: 3, inverse: -3, name: 'three'});
await Integer.create({value: 5, inverse: -5, name: 'five'});
// Initial state.
assert.strictEqual((await Integer.findOne({ where: { value: 2 } })).name, 'two');
assert.strictEqual((await Integer.findOne({ where: { value: 3 } })).name, 'three');
assert.strictEqual((await Integer.findOne({ where: { value: 5 } })).name, 'five');
assert.strictEqual((await Integer.findOne({ where: { value: 2 } })).inverse, -2);
assert.strictEqual((await Integer.findOne({ where: { value: 3 } })).inverse, -3);
assert.strictEqual((await Integer.findOne({ where: { value: 5 } })).inverse, -5);
assert.strictEqual(await Integer.count(), 3);
// Update.
await Integer.bulkCreate(
[
{value: 2, name: 'TWO'},
{value: 3, name: 'THREE'},
{value: 7, name: 'SEVEN'},
],
{ updateOnDuplicate: ["name"] }
);
// Final state.
assert.strictEqual((await Integer.findOne({ where: { value: 2 } })).name, 'TWO');
assert.strictEqual((await Integer.findOne({ where: { value: 3 } })).name, 'THREE');
assert.strictEqual((await Integer.findOne({ where: { value: 5 } })).name, 'five');
assert.strictEqual((await Integer.findOne({ where: { value: 7 } })).name, 'SEVEN');
assert.strictEqual((await Integer.findOne({ where: { value: 2 } })).inverse, -2);
assert.strictEqual((await Integer.findOne({ where: { value: 3 } })).inverse, -3);
assert.strictEqual((await Integer.findOne({ where: { value: 5 } })).inverse, -5);
assert.strictEqual(await Integer.count(), 4);
await sequelize.close();
})();
Run Code Online (Sandbox Code Playgroud)
生成的 SQLite 更新查询:
INSERT INTO `IntegerNames` (`value`,`name`) VALUES (2,'TWO'),(3,'THREE'),(7,'SEVEN')
ON CONFLICT (`value`) DO UPDATE SET `name`=EXCLUDED.`name`;
Run Code Online (Sandbox Code Playgroud)
最小的update
例子
为了补充/sf/answers/4460927061/中提到的内容,您不需要使用固定值进行更新,您还可以使用其他列和 SQL 函数,例如:
const assert = require('assert');
const path = require('path');
const { Sequelize, DataTypes, Op } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.' + path.basename(__filename) + '.sqlite',
});
(async () => {
const Inverses = sequelize.define('Inverses',
{
value: {
type: DataTypes.INTEGER,
primaryKey: true,
},
inverse: {
type: DataTypes.INTEGER,
},
name: {
type: DataTypes.STRING,
},
},
{ timestamps: false }
);
await Inverses.sync({force: true})
await Inverses.create({value: 2, inverse: -2, name: 'two'});
await Inverses.create({value: 3, inverse: -3, name: 'three'});
await Inverses.create({value: 5, inverse: -5, name: 'five'});
// Initial state.
assert.strictEqual((await Inverses.findOne({ where: { value: 2 } })).inverse, -2);
assert.strictEqual((await Inverses.findOne({ where: { value: 3 } })).inverse, -3);
assert.strictEqual((await Inverses.findOne({ where: { value: 5 } })).inverse, -5);
assert.strictEqual(await Inverses.count(), 3);
// Update to fixed value.
await Inverses.update(
{ inverse: 0, },
{ where: { value: { [Op.gt]: 2 } } },
);
assert.strictEqual((await Inverses.findOne({ where: { value: 2 } })).inverse, -2);
assert.strictEqual((await Inverses.findOne({ where: { value: 3 } })).inverse, 0);
assert.strictEqual((await Inverses.findOne({ where: { value: 5 } })).inverse, 0);
assert.strictEqual(await Inverses.count(), 3);
// Update to match another column.
await Inverses.update(
{ inverse: sequelize.col('value'), },
{ where: { value: { [Op.gt]: 2 } } },
);
assert.strictEqual((await Inverses.findOne({ where: { value: 2 } })).inverse, -2);
assert.strictEqual((await Inverses.findOne({ where: { value: 3 } })).inverse, 3);
assert.strictEqual((await Inverses.findOne({ where: { value: 5 } })).inverse, 5);
assert.strictEqual(await Inverses.count(), 3);
// Update to match another column with modification.
await Inverses.update(
{ inverse: sequelize.fn('1 + ', sequelize.col('value')), },
{ where: { value: { [Op.gt]: 2 } } },
);
assert.strictEqual((await Inverses.findOne({ where: { value: 2 } })).inverse, -2);
assert.strictEqual((await Inverses.findOne({ where: { value: 3 } })).inverse, 4);
assert.strictEqual((await Inverses.findOne({ where: { value: 5 } })).inverse, 6);
assert.strictEqual(await Inverses.count(), 3);
// A string function test.
await Inverses.update(
{ name: sequelize.fn('upper', sequelize.col('name')), },
{ where: { value: { [Op.gt]: 2 } } },
);
assert.strictEqual((await Inverses.findOne({ where: { value: 2 } })).name, 'two');
assert.strictEqual((await Inverses.findOne({ where: { value: 3 } })).name, 'THREE');
assert.strictEqual((await Inverses.findOne({ where: { value: 5 } })).name, 'FIVE');
assert.strictEqual(await Inverses.count(), 3);
await sequelize.close();
})();
Run Code Online (Sandbox Code Playgroud)
生成的 SQLite 更新查询:
UPDATE `Inverses` SET `inverse`=$1 WHERE `value` > 2
UPDATE `Inverses` SET `inverse`=`value` WHERE `value` > 2
UPDATE `Inverses` SET `inverse`=1 + (`value`)
UPDATE `Inverses` SET `name`=upper(`name`) WHERE `value` > 2
Run Code Online (Sandbox Code Playgroud)
QueryInterface.bulkUpdate
迁移的最小示例
让我困惑的是,有一个bulkUpdate
forQueryInterface
,但没有forModel
。
部分原因似乎是无法在迁移中进行非原始查询,如以下所述: https: //github.com/sequelize/cli/issues/862对于非原始查询,我们可以使用.update
如上图所示。看来这bulkUpdate
是一个可用于迁移的更原始的版本。
完整的示例如下所示: https: //github.com/cirosantilli/cirodown/blob/bulk-update-col/web/migrations/20210903000000-user-add-display-name-column.js在这个示例中,我是向数据库添加一个新displayName
列,我希望它基于现有username
列。
下面是如何使displayName
与 相同的示例username
。请注意,它实际上并没有使用像 那样的数组输入Model.bulkCreate
,它只是运行 SQLUPDATE
查询,因此命名有点令人困惑:
module.exports = {
up: async (queryInterface, Sequelize) => queryInterface.sequelize.transaction(async transaction => {
await queryInterface.addColumn('User', 'displayName',
{
type: Sequelize.STRING(256),
allowNull: false,
defaultValue: '',
},
{transaction},
)
await queryInterface.bulkUpdate('User',
{displayName: queryInterface.sequelize.col('username')},
{}, // optional where clause to select which rows to update
// If empty like this it updates every single row.
{transaction},
)
}),
down: async (queryInterface, Sequelize) => {
await queryInterface.removeColumn('User', 'displayName')
}
};
Run Code Online (Sandbox Code Playgroud)
相关创建示例:在Sequelize迁移脚本中添加数据?
TODO QueryInterface.bulkInsert
+updateOnDuplicate
迁移的最小示例
好的,现在我想在迁移过程中实际插入一个数组,因为我的修改太复杂了,并且无法在 SQL 中完成bulkUpdate
:我必须将数据引入 Node,然后将其推回。
我希望以下内容能够工作,但事实并非如此,并且考虑到完全缺乏回溯......我不知道为什么:
module.exports = {
up: async (queryInterface, Sequelize) => queryInterface.sequelize.transaction(async transaction => {
await queryInterface.addColumn('User', 'displayName',
{
type: Sequelize.STRING(256),
allowNull: false,
defaultValue: '',
},
{transaction},
)
const [users] = await queryInterface.sequelize.query('SELECT * FROM "User";', { transaction });
const newUsers = users.map(user =>
{ return { id: user.id, displayName: user.username } }
)
await queryInterface.bulkInsert('User',
newUsers,
{
updateOnDuplicate: ['displayName'],
transaction,
}
)
}),
down: async (queryInterface, Sequelize) => {
await queryInterface.removeColumn('User', 'displayName')
}
};
Run Code Online (Sandbox Code Playgroud)
失败并显示:
ERROR: Cannot read property 'map' of undefined
Run Code Online (Sandbox Code Playgroud)
在sequelize 6.5.1、sqlite3 5.0.2、node v14.17.0、Ubuntu 21.04 上测试。
归档时间: |
|
查看次数: |
32812 次 |
最近记录: |