1.15.3 (2023-09-05)
Bug Fixes
- draft globals always displaying unpublish button (9bc072c)
- globals not saving updatedAt and createdAt and version dates correctly (9fbabc8)
Features
✨ Improving version enabled query speed (related PR)
- ➡️ Copy migration script below
- ➡️ Run migration script
- ➡️ Add new property to config
- 🧠 While this migration script is very basic, it is always a good idea to backup your DB before running migrations
1. The migration script
const payload = require('payload');
require('dotenv').config();
const { PAYLOAD_SECRET, MONGODB_URI } = process.env;
// This function adds a `latest` flag for each documents newest version
// to improve query performance on versions/drafts
const improveVersionsQueryPerformance = async () => {
// Initialize Payload
// IMPORTANT: make sure your ENV variables are filled properly here
// as the below variable names are just for reference.
await payload.init({
secret: PAYLOAD_SECRET,
mongoURL: MONGODB_URI,
local: true,
});
async function migrateCollectionDocs(slug: string, docsAtATime = 100) {
const VersionsModel = payload.versions[slug];
const remainingDocs = await VersionsModel.aggregate([
// Sort so that newest are first
{
$sort: {
updatedAt: -1,
},
},
// Group by parent ID
// take the $first of each
{
$group: {
_id: '$parent',
_versionID: { $first: '$_id' },
version: { $first: '$version' },
updatedAt: { $first: '$updatedAt' },
createdAt: { $first: '$createdAt' },
latest: { $first: '$latest' },
},
},
{
$match: {
latest: { $eq: null },
},
},
{
$limit: docsAtATime,
},
], {
allowDiskUse: true,
})
.exec();
if (!remainingDocs || remainingDocs.length === 0) {
const newVersions = await VersionsModel.find({
latest: {
$eq: true
}
})
if (newVersions?.length) {
console.log(`Migrated ${newVersions.length} documents in the "${slug}" versions collection.`)
}
return;
}
const remainingDocIds = remainingDocs.map((doc) => doc._versionID);
await VersionsModel.updateMany(
{
_id: {
$in: remainingDocIds,
},
},
{
latest: true,
},
);
await migrateCollectionDocs(slug);
}
// For each collection
await Promise.all(
payload.config.collections.map(async ({ slug, versions }) => {
if (versions) {
return migrateCollectionDocs(slug);
}
}),
);
// For each global
await Promise.all(
payload.config.globals.map(async ({ slug, versions }) => {
if (versions) {
const VersionsModel = payload.versions[slug];
await VersionsModel.findOneAndUpdate(
{},
{ latest: true },
{
sort: { updatedAt: -1 },
},
).exec();
console.log(`Migrated the "${slug}" global.`)
}
}),
);
console.log('Done!');
process.exit(0);
};
improveVersionsQueryPerformance();
2. Running the script
This step depends on where the script is run from and where you place the script. The example below is assuming you have a similar folder structure and are running it from the root folder:
root
└─ scripts
└─ improveVersionsQueryPerformance.ts
└─ src
└─ payload.config.ts
# the command to run in the root folder
PAYLOAD_CONFIG_PATH=src/payload.config.ts npx ts-node -T scripts/improveVersionsQueryPerformance.ts
3. Adjusting your payload.config.ts file
// file: payload.config.ts
const config = {
// ... rest of your config
database: {
// You can toggle this feature on/off after running the migration
// if you need to revert to querying the previous way
queryDrafts_2_0: true
}
}