javascript - 使用 Sequelize 执行 INSERT 和 UPDATE 查询中的意外顺序

标签 javascript node.js postgresql sequelize.js

首先,我将简要解释我正在尝试做的事情以及相关的模型。

拥有一个 trackingIds 数组(10 个元素),使用这个 trackingId 和一个“免费”调色板创建一个染色体

考虑:

Project.hasMany(models.Palette);
Project.hasMany(models.Chromosome);
Chromosome.hasOne(models.Palette);
Palette.belongsTo(models.Project, {foreignKey: 'projectId', as: 'project'});
Palette.belongsTo(models.Chromosome, {foreignKey: 'chromosomeId', as: 'chromosome'});

现在,我的代码看起来像这样:
freeTrackingIds.forEach(async (trackingId) => {
    // Since the project has many palettes, I want to assign to the chromosome one palette that is free (this means, that has not been assigned to any chromosome yet).
    // I tried to reload() the project to fetch the changes in its palettes in previous iterations
    const availablePalettes = (await project.reload()).palettes.filter((palette) => !palette.chromosomeId);

    // Choosing a random palette from my available palettes. Yes, there might be better ways to achieve this. 
    const randomPalette = availablePalettes[Math.floor(Math.random() * availablePalettes.length)];

    // Creating the new chromosome for the project with the trackingId 
    const chromosome = await Chromosome.create({ projectId: project.id, trackingId: trackingId });

    // Linking the Palette to the chromosome
    randomPalette.chromosomeId = chromosome.id;
    await randomPalette.save();
  });

我注意到 availablePalettes 语句会检索我在此 forEach 的先前迭代中分配的调色板(这就是我决定每次重新加载项目实体的原因)。

即使重新加载项目(返回免费可用的调色板),我也经历过这种情况。
检查我的日志我注意到:
Executing (default): INSERT INTO "Chromosomes" ("id","trackingId","elements","timesRequested","generation","createdAt","updatedAt","projectId") VALUES (DEFAULT,$1,$2,$3,$4,$5,$6,$7) RETURNING *;
Executing (default): INSERT INTO "Chromosomes" ("id","trackingId","elements","timesRequested","generation","createdAt","updatedAt","projectId") VALUES (DEFAULT,$1,$2,$3,$4,$5,$6,$7) RETURNING *;
Executing (default): INSERT INTO "Chromosomes" ("id","trackingId","elements","timesRequested","generation","createdAt","updatedAt","projectId") VALUES (DEFAULT,$1,$2,$3,$4,$5,$6,$7) RETURNING *;
Executing (default): INSERT INTO "Chromosomes" ("id","trackingId","elements","timesRequested","generation","createdAt","updatedAt","projectId") VALUES (DEFAULT,$1,$2,$3,$4,$5,$6,$7) RETURNING *;
Executing (default): INSERT INTO "Chromosomes" ("id","trackingId","elements","timesRequested","generation","createdAt","updatedAt","projectId") VALUES (DEFAULT,$1,$2,$3,$4,$5,$6,$7) RETURNING *;
Executing (default): INSERT INTO "Chromosomes" ("id","trackingId","elements","timesRequested","generation","createdAt","updatedAt","projectId") VALUES (DEFAULT,$1,$2,$3,$4,$5,$6,$7) RETURNING *;
Executing (default): INSERT INTO "Chromosomes" ("id","trackingId","elements","timesRequested","generation","createdAt","updatedAt","projectId") VALUES (DEFAULT,$1,$2,$3,$4,$5,$6,$7) RETURNING *;
Executing (default): INSERT INTO "Chromosomes" ("id","trackingId","elements","timesRequested","generation","createdAt","updatedAt","projectId") VALUES (DEFAULT,$1,$2,$3,$4,$5,$6,$7) RETURNING *;
Executing (default): INSERT INTO "Chromosomes" ("id","trackingId","elements","timesRequested","generation","createdAt","updatedAt","projectId") VALUES (DEFAULT,$1,$2,$3,$4,$5,$6,$7) RETURNING *;
Executing (default): UPDATE "Palettes" SET "chromosomeId"=$1,"updatedAt"=$2 WHERE "id" = $3
Executing (default): UPDATE "Palettes" SET "chromosomeId"=$1,"updatedAt"=$2 WHERE "id" = $3
Executing (default): UPDATE "Palettes" SET "chromosomeId"=$1,"updatedAt"=$2 WHERE "id" = $3
Executing (default): UPDATE "Palettes" SET "chromosomeId"=$1,"updatedAt"=$2 WHERE "id" = $3
Executing (default): UPDATE "Palettes" SET "chromosomeId"=$1,"updatedAt"=$2 WHERE "id" = $3
Executing (default): UPDATE "Palettes" SET "chromosomeId"=$1,"updatedAt"=$2 WHERE "id" = $3
Executing (default): UPDATE "Palettes" SET "chromosomeId"=$1,"updatedAt"=$2 WHERE "id" = $3
Executing (default): UPDATE "Palettes" SET "chromosomeId"=$1,"updatedAt"=$2 WHERE "id" = $3
Executing (default): UPDATE "Palettes" SET "chromosomeId"=$1,"updatedAt"=$2 WHERE "id" = $3

我不确定这是否完全基于时间,但看起来 sequelize(肯定是由于性能原因)在我的调色板分配之前完成了我所有的染色体创建。这可能是 availablePalettes 返回在此 forEach() 的先前迭代中分配给 Chromosomes 的调色板的原因吗?

暂时就这些,先谢谢了!

最佳答案

Array 对象的 forEach func 不支持异步语法。使用“for of”:

forof (const trackingId of freeTrackingIds) {
// Since the project has many palettes, I want to assign to the chromosome one palette that is free (this means, that has not been assigned to any chromosome yet).
    // I tried to reload() the project to fetch the changes in its palettes in previous iterations
    const availablePalettes = (await project.reload()).palettes.filter((palette) => !palette.chromosomeId);

    // Choosing a random palette from my available palettes. Yes, there might be better ways to achieve this. 
    const randomPalette = availablePalettes[Math.floor(Math.random() * availablePalettes.length)];

    // Creating the new chromosome for the project with the trackingId 
    const chromosome = await Chromosome.create({ projectId: project.id, trackingId: trackingId });

    // Linking the Palette to the chromosome
    randomPalette.chromosomeId = chromosome.id;
    await randomPalette.save();  
}

此外,我建议您将事务用于此类批处理操作。

关于javascript - 使用 Sequelize 执行 INSERT 和 UPDATE 查询中的意外顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61329362/

相关文章:

javascript - 如何将 Unicode 字符串拆分为 JavaScript 中的字符

javascript - 为什么不在 DOM 中的对象缺少 jQuery 中的 on 方法?

javascript - 如何使用缓冲区对象作为 Ffmpeg 的源输入

javascript - GitHub Actions - 清空环境 secret

node.js - Webpack 和 Babel : Server Side rendering of React Component "Unexpected token ' <'"

postgresql - Ho 为 Google Cloud SQL Postgresql 实例构建连接 URL

python - Django - 从字符串构建模型过滤器

ASP.NET:通过客户端 JavaScript 在 ASP.NET TreeView 上选择节点

postgresql - 外部数据包装器缓存机制支持

javascript - Phonegap,停止音频