mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
Optimised the storage of collection posts relations
refs https://github.com/TryGhost/Arch/issues/95 Rather than a big nested loop to reconcile the in-memory vs. persisted PostCollections we can instead use the events to know which rows we have to delete and which we have to insert. This removes a tonne of work. This implementation isn't perfect, and misses cases where the same post is added and removed, our use-cases don't currently support that however.
This commit is contained in:
parent
c6f2c985f1
commit
db488b4124
2 changed files with 30 additions and 36 deletions
|
@ -204,45 +204,39 @@ module.exports = class BookshelfCollectionsRepository {
|
|||
transacting: options.transaction
|
||||
});
|
||||
|
||||
const collectionPostsRelations = collection.posts.map((postId, index) => {
|
||||
return {
|
||||
id: (new ObjectID).toHexString(),
|
||||
sort_order: collection.type === 'manual' ? index : 0,
|
||||
collection_id: collection.id,
|
||||
post_id: postId
|
||||
};
|
||||
});
|
||||
|
||||
const collectionPostRelationsToDeleteIds = [];
|
||||
|
||||
if (collection.type === 'manual') {
|
||||
const collectionPostsRelations = collection.posts.map((postId, index) => {
|
||||
return {
|
||||
id: (new ObjectID).toHexString(),
|
||||
sort_order: index,
|
||||
collection_id: collection.id,
|
||||
post_id: postId
|
||||
};
|
||||
});
|
||||
await this.#relationModel.query().delete().where('collection_id', collection.id).transacting(options.transaction);
|
||||
} else {
|
||||
const collectionPostsOptions = {
|
||||
transaction: options.transaction,
|
||||
columns: ['id', 'post_id']
|
||||
};
|
||||
const existingRelations = await this.#fetchCollectionPostIds(collection.id, collectionPostsOptions);
|
||||
|
||||
for (const existingRelation of existingRelations) {
|
||||
const found = collectionPostsRelations.find((thing) => {
|
||||
return thing.post_id === existingRelation.post_id;
|
||||
});
|
||||
if (found) {
|
||||
found.id = null;
|
||||
} else {
|
||||
collectionPostRelationsToDeleteIds.push(existingRelation.id);
|
||||
}
|
||||
if (collectionPostsRelations.length > 0) {
|
||||
await this.#relationModel.query().insert(collectionPostsRelations).transacting(options.transaction);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const collectionPostsToDelete = collection.events.filter(event => event.type === 'CollectionPostRemoved').map((event) => {
|
||||
return event.data.post_id;
|
||||
});
|
||||
|
||||
const missingCollectionPostsRelations = collectionPostsRelations.filter(thing => thing.id !== null);
|
||||
const collectionPostsToInsert = collection.events.filter(event => event.type === 'CollectionPostAdded').map((event) => {
|
||||
return {
|
||||
id: (new ObjectID).toHexString(),
|
||||
sort_order: 0,
|
||||
collection_id: collection.id,
|
||||
post_id: event.data.post_id
|
||||
};
|
||||
});
|
||||
|
||||
if (missingCollectionPostsRelations.length > 0) {
|
||||
await this.#relationModel.query().insert(missingCollectionPostsRelations).transacting(options.transaction);
|
||||
}
|
||||
if (collectionPostRelationsToDeleteIds.length > 0) {
|
||||
await this.#relationModel.query().delete().whereIn('id', collectionPostRelationsToDeleteIds).transacting(options.transaction);
|
||||
if (collectionPostsToDelete.length > 0) {
|
||||
await this.#relationModel.query().delete().where('collection_id', collection.id).whereIn('post_id', collectionPostsToDelete).transacting(options.transaction);
|
||||
}
|
||||
if (collectionPostsToInsert.length > 0) {
|
||||
await this.#relationModel.query().insert(collectionPostsToInsert).transacting(options.transaction);
|
||||
}
|
||||
}
|
||||
|
||||
options.transaction.executionPromise.then(() => {
|
||||
|
|
|
@ -572,7 +572,7 @@ describe('Collections API', function () {
|
|||
}, this.skip.bind(this));
|
||||
|
||||
const collectionRelatedQueries = queries.filter(query => query.sql.includes('collection'));
|
||||
assert.equal(collectionRelatedQueries.length, 13);
|
||||
assert.equal(collectionRelatedQueries.length, 12);
|
||||
}
|
||||
|
||||
await agent
|
||||
|
@ -604,7 +604,7 @@ describe('Collections API', function () {
|
|||
}, this.skip.bind(this));
|
||||
|
||||
const collectionRelatedQueries = queries.filter(query => query.sql.includes('collection'));
|
||||
assert.equal(collectionRelatedQueries.length, 18);
|
||||
assert.equal(collectionRelatedQueries.length, 16);
|
||||
}
|
||||
|
||||
await agent
|
||||
|
|
Loading…
Add table
Reference in a new issue