feat: 更新 replace-team-qrcode-url 脚本以支持 staff-qrcode 集合的前缀替换
This commit is contained in:
parent
525d9fa1d8
commit
73e9875d40
@ -5,6 +5,8 @@
|
|||||||
* 目的:
|
* 目的:
|
||||||
* - 扫描 corp.team collection
|
* - 扫描 corp.team collection
|
||||||
* - 将 team.qrcodes[].qrcode 中旧前缀替换为新前缀
|
* - 将 team.qrcodes[].qrcode 中旧前缀替换为新前缀
|
||||||
|
* - 扫描 corp.staff-qrcode collection
|
||||||
|
* - 将 staff-qrcode.archiveLink.url 中旧前缀替换为新前缀
|
||||||
*
|
*
|
||||||
* 安全:
|
* 安全:
|
||||||
* - 默认 dry-run(不落库)
|
* - 默认 dry-run(不落库)
|
||||||
@ -70,6 +72,7 @@ function createDefaultOptions() {
|
|||||||
return {
|
return {
|
||||||
dbName: "corp",
|
dbName: "corp",
|
||||||
collection: "team",
|
collection: "team",
|
||||||
|
staffCollection: "staff-qrcode",
|
||||||
batchDocs: 200,
|
batchDocs: 200,
|
||||||
skipDocs: 0,
|
skipDocs: 0,
|
||||||
limitDocs: 0,
|
limitDocs: 0,
|
||||||
@ -107,6 +110,7 @@ function parseArgs(argv) {
|
|||||||
if (!key) return;
|
if (!key) return;
|
||||||
if (key === "dbname" || key === "db") opts.dbName = value;
|
if (key === "dbname" || key === "db") opts.dbName = value;
|
||||||
else if (key === "collection") opts.collection = value;
|
else if (key === "collection") opts.collection = value;
|
||||||
|
else if (key === "staffcollection") opts.staffCollection = value;
|
||||||
else if (key === "mongouri" || key === "mongourl") opts.mongoUri = value;
|
else if (key === "mongouri" || key === "mongourl") opts.mongoUri = value;
|
||||||
else if (key === "mongourienv") opts.mongoUriEnv = value;
|
else if (key === "mongourienv") opts.mongoUriEnv = value;
|
||||||
else if (key === "mongohost") opts.mongoHost = value;
|
else if (key === "mongohost") opts.mongoHost = value;
|
||||||
@ -144,6 +148,9 @@ function parseArgs(argv) {
|
|||||||
} else if (a === "--collection") {
|
} else if (a === "--collection") {
|
||||||
opts.collection = takeValue(i);
|
opts.collection = takeValue(i);
|
||||||
i++;
|
i++;
|
||||||
|
} else if (a === "--staffCollection") {
|
||||||
|
opts.staffCollection = takeValue(i);
|
||||||
|
i++;
|
||||||
} else if (a === "--mongoUri" || a === "--mongoUrl" || a === "--mongoURL") {
|
} else if (a === "--mongoUri" || a === "--mongoUrl" || a === "--mongoURL") {
|
||||||
opts.mongoUri = takeValue(i);
|
opts.mongoUri = takeValue(i);
|
||||||
i++;
|
i++;
|
||||||
@ -290,6 +297,75 @@ function updateTeamDoc(doc, { oldPrefix, newPrefix }) {
|
|||||||
return { changed, nextQrcodes };
|
return { changed, nextQrcodes };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateStaffQrcodeDoc(doc, { oldPrefix, newPrefix }) {
|
||||||
|
const archiveLink =
|
||||||
|
doc && doc.archiveLink && typeof doc.archiveLink === "object"
|
||||||
|
? doc.archiveLink
|
||||||
|
: null;
|
||||||
|
if (!archiveLink) {
|
||||||
|
return { changed: 0, nextArchiveLink: archiveLink };
|
||||||
|
}
|
||||||
|
const current = archiveLink.url;
|
||||||
|
const next = replacePrefix(current, oldPrefix, newPrefix);
|
||||||
|
if (next === current) {
|
||||||
|
return { changed: 0, nextArchiveLink: archiveLink };
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
changed: 1,
|
||||||
|
nextArchiveLink: { ...archiveLink, url: next },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function processCollectionDocs({
|
||||||
|
collection,
|
||||||
|
filter,
|
||||||
|
batchDocs,
|
||||||
|
sortById,
|
||||||
|
skipDocs,
|
||||||
|
limitDocs,
|
||||||
|
dryRun,
|
||||||
|
updateDoc,
|
||||||
|
buildUpdate,
|
||||||
|
describeDoc,
|
||||||
|
}) {
|
||||||
|
let cursor = collection.find(filter, { batchSize: batchDocs });
|
||||||
|
if (sortById) cursor = cursor.sort({ _id: 1 });
|
||||||
|
if (skipDocs) cursor = cursor.skip(skipDocs);
|
||||||
|
if (limitDocs) cursor = cursor.limit(limitDocs);
|
||||||
|
|
||||||
|
let scanned = 0;
|
||||||
|
let matchedDocs = 0;
|
||||||
|
let replacedUrls = 0;
|
||||||
|
let batchIndex = 0;
|
||||||
|
|
||||||
|
while (await cursor.hasNext()) {
|
||||||
|
const batch = [];
|
||||||
|
while (batch.length < batchDocs && (await cursor.hasNext())) {
|
||||||
|
batch.push(await cursor.next());
|
||||||
|
}
|
||||||
|
if (batch.length === 0) break;
|
||||||
|
batchIndex++;
|
||||||
|
console.log(
|
||||||
|
`[step] ${collection.collectionName} batch#${batchIndex} 读取文档 ${batch.length} 条(已扫描 ${scanned} 条)`
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const doc of batch) {
|
||||||
|
scanned++;
|
||||||
|
const { changed, ...payload } = updateDoc(doc);
|
||||||
|
if (changed === 0) continue;
|
||||||
|
matchedDocs++;
|
||||||
|
replacedUrls += changed;
|
||||||
|
console.log(`[match] ${collection.collectionName} ${describeDoc(doc)} replaced=${changed}`);
|
||||||
|
|
||||||
|
if (!dryRun) {
|
||||||
|
await collection.updateOne({ _id: doc._id }, buildUpdate(payload));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { scanned, matchedDocs, replacedUrls };
|
||||||
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const opts = parseArgs(process.argv);
|
const opts = parseArgs(process.argv);
|
||||||
applyEnvFallbacks(opts);
|
applyEnvFallbacks(opts);
|
||||||
@ -336,52 +412,57 @@ async function main() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const db = client.db(opts.dbName);
|
const db = client.db(opts.dbName);
|
||||||
const col = db.collection(opts.collection);
|
const teamCol = db.collection(opts.collection);
|
||||||
|
const staffCol = db.collection(opts.staffCollection);
|
||||||
const filter = {};
|
const filter = {};
|
||||||
if (isNonEmptyString(opts.corpId)) filter.corpId = opts.corpId;
|
if (isNonEmptyString(opts.corpId)) filter.corpId = opts.corpId;
|
||||||
|
|
||||||
console.log(`[step] collection=${opts.dbName}.${opts.collection} corpId=${opts.corpId || "全部"} mode=${opts.dryRun ? "dry-run" : "apply"}`);
|
console.log(
|
||||||
let cursor = col.find(filter, { batchSize: opts.batchDocs });
|
`[step] collection=${opts.dbName}.${opts.collection} corpId=${opts.corpId || "全部"} mode=${opts.dryRun ? "dry-run" : "apply"}`
|
||||||
if (opts.sortById) cursor = cursor.sort({ _id: 1 });
|
);
|
||||||
if (opts.skipDocs) cursor = cursor.skip(opts.skipDocs);
|
const teamStats = await processCollectionDocs({
|
||||||
if (opts.limitDocs) cursor = cursor.limit(opts.limitDocs);
|
collection: teamCol,
|
||||||
|
filter,
|
||||||
let scanned = 0;
|
batchDocs: opts.batchDocs,
|
||||||
let matchedDocs = 0;
|
sortById: opts.sortById,
|
||||||
let replacedUrls = 0;
|
skipDocs: opts.skipDocs,
|
||||||
let batchIndex = 0;
|
limitDocs: opts.limitDocs,
|
||||||
|
dryRun: opts.dryRun,
|
||||||
while (await cursor.hasNext()) {
|
updateDoc: (doc) =>
|
||||||
const batch = [];
|
updateTeamDoc(doc, {
|
||||||
while (batch.length < opts.batchDocs && (await cursor.hasNext())) {
|
|
||||||
batch.push(await cursor.next());
|
|
||||||
}
|
|
||||||
if (batch.length === 0) break;
|
|
||||||
batchIndex++;
|
|
||||||
console.log(`[step] batch#${batchIndex} 读取文档 ${batch.length} 条(已扫描 ${scanned} 条)`);
|
|
||||||
|
|
||||||
for (const doc of batch) {
|
|
||||||
scanned++;
|
|
||||||
const { changed, nextQrcodes } = updateTeamDoc(doc, {
|
|
||||||
oldPrefix: opts.oldPrefix,
|
oldPrefix: opts.oldPrefix,
|
||||||
newPrefix: opts.newPrefix,
|
newPrefix: opts.newPrefix,
|
||||||
});
|
}),
|
||||||
if (changed === 0) continue;
|
buildUpdate: ({ nextQrcodes }) => ({ $set: { qrcodes: nextQrcodes } }),
|
||||||
matchedDocs++;
|
describeDoc: (doc) =>
|
||||||
replacedUrls += changed;
|
`_id=${doc._id} teamId=${doc.teamId || ""} corpId=${doc.corpId || ""}`,
|
||||||
console.log(`[match] _id=${doc._id} teamId=${doc.teamId || ""} corpId=${doc.corpId || ""} replaced=${changed}`);
|
});
|
||||||
|
|
||||||
if (!opts.dryRun) {
|
|
||||||
await col.updateOne(
|
|
||||||
{ _id: doc._id },
|
|
||||||
{ $set: { qrcodes: nextQrcodes } }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`[summary] scanned=${scanned} matchedDocs=${matchedDocs} replacedUrls=${replacedUrls} mode=${opts.dryRun ? "dry-run" : "apply"}`
|
`[step] collection=${opts.dbName}.${opts.staffCollection} corpId=${opts.corpId || "全部"} mode=${opts.dryRun ? "dry-run" : "apply"}`
|
||||||
|
);
|
||||||
|
const staffStats = await processCollectionDocs({
|
||||||
|
collection: staffCol,
|
||||||
|
filter,
|
||||||
|
batchDocs: opts.batchDocs,
|
||||||
|
sortById: opts.sortById,
|
||||||
|
skipDocs: opts.skipDocs,
|
||||||
|
limitDocs: opts.limitDocs,
|
||||||
|
dryRun: opts.dryRun,
|
||||||
|
updateDoc: (doc) =>
|
||||||
|
updateStaffQrcodeDoc(doc, {
|
||||||
|
oldPrefix: opts.oldPrefix,
|
||||||
|
newPrefix: opts.newPrefix,
|
||||||
|
}),
|
||||||
|
buildUpdate: ({ nextArchiveLink }) => ({
|
||||||
|
$set: { archiveLink: nextArchiveLink },
|
||||||
|
}),
|
||||||
|
describeDoc: (doc) =>
|
||||||
|
`_id=${doc._id} qrcodeId=${doc.qrcodeId || ""} corpId=${doc.corpId || ""}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`[summary] team: scanned=${teamStats.scanned} matchedDocs=${teamStats.matchedDocs} replacedUrls=${teamStats.replacedUrls} | staff-qrcode: scanned=${staffStats.scanned} matchedDocs=${staffStats.matchedDocs} replacedUrls=${staffStats.replacedUrls} mode=${opts.dryRun ? "dry-run" : "apply"}`
|
||||||
);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
await client.close();
|
await client.close();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user