Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: save and update many with one connect to bd[3966] #4127

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c32a4a7
feat: save and update many with one connect to bd[3966]
Sep 8, 2024
8b2bd02
feat: add many methods in db service[3966]
Sep 8, 2024
edc0bdf
fix: lint errors
Sep 8, 2024
6efa047
Merge branch 'develop' into feature/3966-database-access-layer-refact…
Sep 11, 2024
59d552a
Merge branch 'develop' into feature/3966-database-access-layer-refact…
ihar-tsykala Sep 11, 2024
b4e958a
Feature/3966 database access layer refactoring impruving requests db …
ihar-tsykala Sep 12, 2024
1c2f6ab
Merge branch 'develop' into feature/3966-database-access-layer-refact…
ihar-tsykala Sep 12, 2024
716a6bf
refactore code
Sep 12, 2024
8017153
fix: issue update many get collection for bulk write[3966]
Sep 15, 2024
a51b450
feat: add multi entities in tests[3966]
Sep 15, 2024
866b4e1
fix: swich update schemas in db server to update db helper[3966]
Sep 18, 2024
ebfa5f5
fix: delete update many[3966]
Sep 19, 2024
c66a3cd
fix: remove save many from queue service[3966]
Sep 20, 2024
998dbe7
Revert "fix: remove save many from queue service[3966]"
Sep 20, 2024
3a53696
Revert "fix: delete update many[3966]"
Sep 20, 2024
e2c2044
Revert "Revert "fix: remove save many from queue service[3966]""
Sep 20, 2024
c0ab216
fix: remove apdate many for contracts[3966]
Sep 22, 2024
ca20761
Merge branch 'develop' into feature/3966-database-access-layer-refact…
Oct 2, 2024
c9f2741
fix: remove promice all from update array[3966]
Oct 2, 2024
5822ae4
refactor code
Oct 4, 2024
1eb4c01
refactor code
Oct 7, 2024
d4f7d14
Merge branch 'develop' into feature/3966-database-access-layer-refact…
ihar-tsykala Oct 7, 2024
694490d
fix: lint errors
Oct 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 97 additions & 19 deletions common/src/database-modules/database-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,10 @@ export class DatabaseServer extends AbstractDatabaseServer {
* @param filter
*/
async save<T extends BaseEntity>(entityClass: new () => T, item: unknown | unknown[], filter?: FilterObject<T>): Promise<T> {
if(Array.isArray(item)) {
return await this.saveMany(entityClass, item, filter) as any
}

if (this.dryRun) {
this.addDryRunId(entityClass, item);
return await new DataBaseHelper(DryRun).save(item, filter) as unknown as T;
Expand All @@ -402,6 +406,20 @@ export class DatabaseServer extends AbstractDatabaseServer {
return await new DataBaseHelper(entityClass).save(item as Partial<T>, filter)
}

/**
* Save many
* @param entityClass
* @param item
* @param filter
*/
async saveMany<T extends BaseEntity>(entityClass: new () => T, item: unknown[], filter?: FilterObject<T>): Promise<T[]> {
if (this.dryRun) {
this.addDryRunId(entityClass, item);
return await new DataBaseHelper(DryRun).saveMany(item, filter) as unknown as T[];
}
return await new DataBaseHelper(entityClass).saveMany(item as Partial<T>[], filter)
}

/**
* Overriding the update method
* @param entityClass
Expand All @@ -411,8 +429,12 @@ export class DatabaseServer extends AbstractDatabaseServer {
async update<T extends BaseEntity>(
entityClass: new () => T,
criteria: FilterQuery<T>,
row: unknown
row: unknown | unknown[]
): Promise<T> {
if(Array.isArray(criteria)) {
return await this.updateMany(entityClass, row as unknown as T[], criteria) as any
}

if (this.dryRun) {
this.addDryRunId(entityClass, row);
return (await new DataBaseHelper(DryRun).update(row as DryRun, criteria as FilterQuery<DryRun>)) as unknown as T;
Expand All @@ -421,6 +443,25 @@ export class DatabaseServer extends AbstractDatabaseServer {
}
}

/**
* Update many method
* @param entityClass
* @param entities
* @param filter
*/
async updateMany<T extends BaseEntity>(
entityClass: new () => T,
entities: T[],
filter?: FilterQuery<T>,
): Promise<DryRun[] | T[]> {
if (this.dryRun) {
this.addDryRunId(entityClass, entities);
return (await new DataBaseHelper(DryRun).updateMany(entities as unknown as DryRun[], filter as FilterQuery<DryRun>));
} else {
return await new DataBaseHelper(entityClass).updateMany(entities as T[], filter);
}
}

/**
* Overriding the remove method
* @param entityClass
Expand Down Expand Up @@ -1363,7 +1404,7 @@ export class DatabaseServer extends AbstractDatabaseServer {
for (const group of groups) {
group.active = group.uuid === uuid;
}
await this.save(PolicyRolesCollection, groups as unknown);
await this.saveMany(PolicyRolesCollection, groups);
}

/**
Expand Down Expand Up @@ -1723,7 +1764,7 @@ export class DatabaseServer extends AbstractDatabaseServer {
* @param residue
*/
public async setResidue(residue: SplitDocuments[]): Promise<void> {
await this.save(SplitDocuments, residue as unknown);
await this.saveMany(SplitDocuments, residue);
}

/**
Expand Down Expand Up @@ -1852,12 +1893,20 @@ export class DatabaseServer extends AbstractDatabaseServer {
return await this.remove(Tag, tag);
}

/**
* Update tag
* @param tag
*/
public async updateTag(tag: Tag): Promise<Tag> {
return await this.update(Tag, tag.id, tag);
}

/**
* Update tags
* @param row
* @param tags
*/
public async updateTag(row: Tag): Promise<Tag> {
return await this.update(Tag, row.id, row);
public async updateTags(tags: Tag[]): Promise<DryRun[] | Tag[]> {
return await this.updateMany(Tag, tags)
}

/**
Expand Down Expand Up @@ -2338,23 +2387,19 @@ export class DatabaseServer extends AbstractDatabaseServer {
}

/**
* Get schema
* Save schema
* @param item
*/
public static async saveSchema(item: SchemaCollection): Promise<SchemaCollection> {
return await new DataBaseHelper(SchemaCollection).save(item);
}

/**
* Get schema
* @param item
* Save schemas
* @param items
*/
public static async saveSchemas(item: SchemaCollection[]): Promise<SchemaCollection[]> {
const result = [];
for await (const schema of item) {
result.push(await new DataBaseHelper(SchemaCollection).save(schema));
}
return result;
public static async saveSchemas(items: SchemaCollection[]): Promise<SchemaCollection[]> {
return await new DataBaseHelper(SchemaCollection).saveMany(items);
}

/**
Expand Down Expand Up @@ -2479,13 +2524,21 @@ export class DatabaseServer extends AbstractDatabaseServer {
}

/**
* Get policy
* Update policy
* @param model
*/
public static async updatePolicy(model: Policy): Promise<Policy> {
return await new DataBaseHelper(Policy).save(model);
}

/**
* Update policies
* @param models
*/
public static async savePolicies(models: Policy[]): Promise<Policy[]> {
return await new DataBaseHelper(Policy).saveMany(models);
}

/**
* Get policies and count
* @param filters
Expand Down Expand Up @@ -2934,6 +2987,15 @@ export class DatabaseServer extends AbstractDatabaseServer {
return await new DataBaseHelper(ArtifactCollection).save(artifact);
}

/**
* Save Artifacts
* @param artifacts Artifacts
* @returns Saved Artifacts
*/
public static async saveArtifacts(artifacts: ArtifactCollection[]): Promise<ArtifactCollection[]> {
return await new DataBaseHelper(ArtifactCollection).saveMany(artifacts);
}

/**
* Get Artifact
* @param filters Filters
Expand Down Expand Up @@ -3293,12 +3355,20 @@ export class DatabaseServer extends AbstractDatabaseServer {
return await new DataBaseHelper(Tag).find(filters, options);
}

/**
* Update tag
* @param tag
*/
public static async updateTag(tag: Tag): Promise<Tag> {
return await new DataBaseHelper(Tag).update(tag);
}

/**
* Update tags
* @param row
* @param tags
*/
public static async updateTag(row: Tag): Promise<Tag> {
return await new DataBaseHelper(Tag).update(row);
public static async updateTags(tags: Tag[]): Promise<Tag[]> {
return await new DataBaseHelper(Tag).updateMany(tags);
}

/**
Expand Down Expand Up @@ -3327,6 +3397,14 @@ export class DatabaseServer extends AbstractDatabaseServer {
return await new DataBaseHelper(TagCache).update(row);
}

/**
* Update tags cache
* @param rows
*/
public static async updateTagsCache(rows: TagCache[]): Promise<TagCache[]> {
return await new DataBaseHelper(TagCache).updateMany(rows);
}

/**
* Create Theme
* @param theme
Expand Down
127 changes: 122 additions & 5 deletions common/src/helpers/db-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -665,11 +665,7 @@ export class DataBaseHelper<T extends BaseEntity> extends AbstractDataBaseHelper
filter?: FilterObject<T>
): Promise<T | T[]> {
if (Array.isArray(entity)) {
const result = [];
for (const item of entity) {
result.push(await this.save(item));
}
return result;
return await Promise.all(entity.map(item => this.save(item)));
}

const repository = this._em.getRepository(this.entityClass);
Expand Down Expand Up @@ -699,6 +695,59 @@ export class DataBaseHelper<T extends BaseEntity> extends AbstractDataBaseHelper
return entityToUpdateOrCreate;
}

@CreateRequestContext(() => DataBaseHelper.orm)
public async saveMany(
entities:Partial<T>[],
filter?: FilterObject<T>
): Promise<T[]> {
const repository = this._em.getRepository(this.entityClass);

let existingEntityByFilter;
let existingEntitiesById: T[] = [];

if(filter) {
existingEntityByFilter = await repository.findOne(filter);
} else {
const ids = entities.map(entity => entity.id || entity._id).filter(id => id);
if (ids.length > 0) {
existingEntitiesById = await repository.find({ id: { $in: ids } });
}
}

const entitiesToUpdateOrCreate = []

for (const entity of entities) {
if (!entity.id && !entity._id && !filter) {
const entityToCreate = repository.create(Object.assign({}, entity));
this._em.persist(entityToCreate)
entitiesToUpdateOrCreate.push(entityToCreate);
continue
}

let entityToUpdateOrCreate = existingEntityByFilter
?? existingEntitiesById.find((existingEntity: T) => existingEntity.id === entity.id);

if (entityToUpdateOrCreate) {
for (const systemFileField of DataBaseHelper._systemFileFields) {
if (entity[systemFileField]) {
delete entity[systemFileField]
}
}

wrap(entityToUpdateOrCreate).assign({ ...entity, updateDate: new Date() } as EntityData<T>, { merge: false });
} else {
entityToUpdateOrCreate = repository.create({ ...entity });
}

this._em.persist(entityToUpdateOrCreate);
entitiesToUpdateOrCreate.push(entityToUpdateOrCreate);
}

await this._em.flush();

return entitiesToUpdateOrCreate;
}

/**
* Update entity by id field or filters
* @param entity Entity
Expand Down Expand Up @@ -748,6 +797,74 @@ export class DataBaseHelper<T extends BaseEntity> extends AbstractDataBaseHelper
: entitiesToUpdate;
}

@CreateRequestContext(() => DataBaseHelper.orm)
public async updateMany(
entities: T[],
filter?: FilterQuery<T>
): Promise<T[]> {
const repository = this._em.getRepository(this.entityClass);
let existingEntityByFilter;
let existingEntitiesById: T[] = [];

const bulkOps = [];
const updatedDocuments = [];

if(filter) {
existingEntityByFilter = await repository.find(filter);
} else {
const ids = entities.map(entity => entity.id || entity._id).filter(id => id);
if (ids.length > 0) {
existingEntitiesById = await repository.find({ id: { $in: ids } });
}
}

for (const entity of entities) {
const id = entity.id || entity._id;

if (!filter && !id) {
continue;
}

let entitiesToUpdate = existingEntityByFilter

if(!entitiesToUpdate) {
const existingEntityById = existingEntitiesById.find((existingEntity: T) => existingEntity.id === entity.id)

if(existingEntityById) {
entitiesToUpdate = [existingEntityById]
} else {
entitiesToUpdate = []
}
}

for (const systemFileField of DataBaseHelper._systemFileFields) {
if (entity[systemFileField]) {
delete entity[systemFileField]
}
}

for (const entityToUpdate of entitiesToUpdate) {
wrap(entityToUpdate).assign({ ...entity, updateDate: new Date() } as EntityData<T>, { mergeObjectProperties: false });

bulkOps.push({
updateOne: {
filter: { _id: id },
update: { $set: entityToUpdate },
}
});

updatedDocuments.push(entityToUpdate);
}
}

if (bulkOps.length > 0) {
const collection = this._em.getDriver().getConnection().getCollection(this.entityClass.name);
await collection.bulkWrite(bulkOps);
}

return updatedDocuments;
}

/**
* Create a lot of data
* @param data Data
Expand Down
Loading