首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >bulkUpdate在后置orm中的应用

bulkUpdate在后置orm中的应用
EN

Stack Overflow用户
提问于 2019-02-27 06:01:17
回答 3查看 59.6K关注 0票数 33

我们如何在后缀orm中实现像bulkUpdate这样的bulkCreate,我搜索了整个封存文档,但是没有找到任何与bulkUpdate相关的文档,所以我尝试在for循环中循环更新,它可以工作,但是还有其他方法来批量更新吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-02-27 08:00:14

使用bulkCreate to bulkUpdate方法。

代码语言:javascript
复制
bulkCreate([...], { updateOnDuplicate: ["name"] })

updateOnDuplicate是一个字段数组,当主键(或可能是唯一键)匹配行时,这些字段将被更新。确保您的模型和dataArray中至少有一个唯一字段(假设id),这两个字段都用于向上插入。

供参考请参阅这里

票数 56
EN

Stack Overflow用户

发布于 2020-09-03 16:03:50

你可以,如果你想用相同的值更新很多记录!示例:我希望每次为10个用户更新字段"activationStatus“,在DB中更新1个用户=1条记录,然后我有用户in数组:

代码语言:javascript
复制
User.update({ activationStatus: 'active'}, {
          where: {
              id: [1,2,3,4,5,6,7,8,9,10]
          }
      });

它将类似于SQL查询:

代码语言:javascript
复制
UPDATE User SET activationStatus = 'active' WHERE id IN(1,2,3,4,5,6,7,8,9,10);

您可以找到更多有关后缀操作符别名这里的信息。

票数 32
EN

Stack Overflow用户

发布于 2021-09-03 11:23:41

最小bulkCreate updateOnDuplicate + updateOnDuplicate示例

只是为了澄清在https://stackoverflow.com/a/54900639/895245上提到了什么

代码语言:javascript
复制
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();
})();

生成的SQLite更新查询:

代码语言:javascript
复制
INSERT INTO `IntegerNames` (`value`,`name`) VALUES (2,'TWO'),(3,'THREE'),(7,'SEVEN')
  ON CONFLICT (`value`) DO UPDATE SET `name`=EXCLUDED.`name`;

update 最小示例

为了补充在https://stackoverflow.com/a/63727529/895245中提到的内容,您不需要使用固定值进行更新,还可以使用其他列和SQL函数,例如:

代码语言:javascript
复制
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();
})();

生成的SQLite更新查询:

代码语言:javascript
复制
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

QueryInterface.bulkUpdate 迁移的最小示例

让我困惑的是有QueryInterface,但没有一个Model

部分原因似乎是没有办法在迁移中进行非原始查询,如: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列,并希望它基于现有的username列。

下面是一个如何使displayNameusername相同的示例。注意,它实际上并没有使用像Model.bulkCreate这样的数组输入,它只是运行一个SQL UPDATE查询,所以命名有点混乱:

代码语言:javascript
复制
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')
  }
};

创建的相关示例:在后缀迁移脚本中添加数据?

迁移QueryInterface.bulkInsertTODO + 最小示例

好的,现在我想在迁移过程中实际插入一个数组,因为我的修改太复杂了,不能在SQL中使用bulkUpdate完成:我必须将数据导入Node,然后将其推回去。

我希望下面的方法能起作用,但没有,而且由于完全没有回溯痕迹.我不知道为什么:

代码语言:javascript
复制
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')
  }
};

在以下方面失败:

代码语言:javascript
复制
ERROR: Cannot read property 'map' of undefined

测试的后缀6.5.1,sqlite3 5.0.2,节点v14.17.0,Ubuntu21.04。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54898994

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档