fix(core): fix batch update query logic (#2230)

This commit is contained in:
Junyi 2023-07-11 15:54:04 +07:00 committed by GitHub
parent 1fb15de29a
commit ff7b1aaf71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 11 deletions

View File

@ -596,6 +596,37 @@ describe('repository.update', () => {
}); });
expect(p1Updated2.userId).toBe(u1.id); expect(p1Updated2.userId).toBe(u1.id);
}); });
it('update in batch filtered by belongsTo field as deep association field', async () => {
const u1 = await User.repository.create({ values: { name: 'u1' } });
const u2 = await User.repository.create({ values: { name: 'u2' } });
const p1 = await Post.repository.create({ values: { name: 'p1', userId: u1.id } });
const p2 = await Post.repository.create({ values: { name: 'p2', userId: u1.id } });
const p3 = await Post.repository.create({ values: { name: 'p3', userId: u2.id } });
const r1 = await Post.repository.update({
filter: {
user: {
id: {
$eq: u1.id
},
},
},
values: {
name: 'p1_1',
},
individualHooks: false,
});
expect(r1).toEqual(2);
const updated = await Post.repository.find({
filter: {
id: [p1.id, p2.id],
}
});
expect(updated.map(item => item.name)).toEqual(['p1_1', 'p1_1']);
});
}); });
describe('repository.destroy', () => { describe('repository.destroy', () => {

View File

@ -607,8 +607,6 @@ export class Repository<TModelAttributes extends {} = any, TCreationAttributes e
const values = guard.sanitize(options.values); const values = guard.sanitize(options.values);
const queryOptions = this.buildQueryOptions(options);
// NOTE: // NOTE:
// 1. better to be moved to separated API like bulkUpdate/updateMany // 1. better to be moved to separated API like bulkUpdate/updateMany
// 2. strictly `false` comparing for compatibility of legacy api invoking // 2. strictly `false` comparing for compatibility of legacy api invoking
@ -620,16 +618,12 @@ export class Repository<TModelAttributes extends {} = any, TCreationAttributes e
// 1. find ids first for reusing `queryOptions` logic // 1. find ids first for reusing `queryOptions` logic
// 2. estimation memory usage will be N * M bytes (N = rows, M = model object memory) // 2. estimation memory usage will be N * M bytes (N = rows, M = model object memory)
// 3. would be more efficient up to 100000 ~ 1000000 rows // 3. would be more efficient up to 100000 ~ 1000000 rows
const rows = await Model.findAll({ const queryOptions = this.buildQueryOptions({
...options,
fields: [primaryKeyField],
});
const rows = await this.find({
...queryOptions, ...queryOptions,
attributes: [primaryKeyField],
group: `${Model.name}.${primaryKeyField}`,
include: queryOptions.include.filter((include) => {
return (
Object.keys(include.where || {}).length > 0 ||
JSON.stringify(queryOptions?.filter)?.includes(include.association)
);
}),
transaction, transaction,
}); });
const [result] = await Model.update(values, { const [result] = await Model.update(values, {
@ -648,6 +642,8 @@ export class Repository<TModelAttributes extends {} = any, TCreationAttributes e
return result; return result;
} }
const queryOptions = this.buildQueryOptions(options);
const instances = await this.find({ const instances = await this.find({
...queryOptions, ...queryOptions,
transaction, transaction,