Skip to content

Commit cc1c879

Browse files
authored
Script to backfill empty mediums (#3255)
1 parent 22ba014 commit cc1c879

File tree

2 files changed

+66
-0
lines changed

2 files changed

+66
-0
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { groupBy } from '@seedcompany/common';
2+
import { node } from 'cypher-query-builder';
3+
import { uniq } from 'lodash';
4+
import { ID } from '~/common';
5+
import { BaseMigration, Migration } from '~/core/database';
6+
import { updateProperty, variable } from '~/core/database/query';
7+
import { ProductMedium as Medium, Product } from '../dto';
8+
import { ProductService } from '../product.service';
9+
10+
@Migration('2024-06-24T09:00:00')
11+
export class BackfillEmptyMediumsMigration extends BaseMigration {
12+
constructor(private readonly productService: ProductService) {
13+
super();
14+
}
15+
16+
async up() {
17+
const engagements = await this.db.query<
18+
Array<{ id: ID; mediums: Medium[] }>
19+
>().raw`
20+
match (eng:Engagement)
21+
where exists((eng)-[:product { active: true }]->(:Product)-[:mediums { active: true }]->(:Property { value: [] }))
22+
match (eng)-[:product { active: true }]->(prod:Product)-[:mediums { active: true }]->(mediums:Property)
23+
with eng, collect({ id: prod.id, mediums: mediums.value }) as products
24+
where any(product in products where size(product.mediums) > 0)
25+
return products
26+
`.run();
27+
this.logger.notice(
28+
`Found ${engagements.length} engagements with some empty mediums`,
29+
);
30+
31+
const updates = engagements.flatMap((products) => {
32+
const grouped = groupBy(products, (p) =>
33+
uniq(p.mediums)
34+
.sort((a, b) => a.localeCompare(b))
35+
.join(';'),
36+
);
37+
if (grouped.length > 2) {
38+
return [];
39+
}
40+
const [nonEmpties, empties] =
41+
grouped[0][0].mediums.length > 0 ? grouped : grouped.toReversed();
42+
43+
const mediums = nonEmpties[0].mediums;
44+
return empties.map((p) => ({ id: p.id, mediums }));
45+
});
46+
this.logger.notice(
47+
`Resolves to ${updates.length} products to assign mediums to`,
48+
);
49+
50+
await this.db
51+
.query()
52+
.unwind(updates, 'update')
53+
.match(node('product', 'Product', { id: variable('update.id') }))
54+
.apply(
55+
updateProperty({
56+
resource: Product,
57+
key: 'mediums',
58+
value: variable('update.mediums'),
59+
}),
60+
)
61+
.return<{ id: ID }>('product.id as id')
62+
.executeAndLogStats();
63+
}
64+
}

src/components/product/product.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { FileModule } from '../file/file.module';
44
import { ScriptureModule } from '../scripture';
55
import { StoryModule } from '../story/story.module';
66
import * as handlers from './handlers';
7+
import { BackfillEmptyMediumsMigration } from './migrations/backfill-empty-mediums.migration';
78
import { FixNaNTotalVerseEquivalentsMigration } from './migrations/fix-nan-total-verse-equivalents.migration';
89
import { ProducibleResolver } from './producible.resolver';
910
import { ProductExtractor } from './product-extractor.service';
@@ -27,6 +28,7 @@ import { ProductService } from './product.service';
2728
ProductRepository,
2829
ProductExtractor,
2930
FixNaNTotalVerseEquivalentsMigration,
31+
BackfillEmptyMediumsMigration,
3032
...Object.values(handlers),
3133
],
3234
exports: [ProductService],

0 commit comments

Comments
 (0)