[英]MongoDB: How to find and replace ObjectId across collection
我正在將兩個文檔合二為一。 為此,我想用對 DocB 的引用替換對 DocA 的所有引用。
我想對數據庫中的所有文檔和所有集合執行此操作。 在集合/模型中,對此類文檔的每個引用都使用相同的鍵“docFieldKey”。 然而,路徑通常是不同的,所以有時它在頂層,有時在文檔中的一組對象中。
ExModelA: {
_id: ObjectId,
docFieldKey: string // if docAId, replace with docBId
}
對 docA 的引用可能位於子字段中,例如:
ExModelB: {
_id: ObjectId,
someKey: {
docFieldKey: string // if docAId, replace with docBId
}
}
DocAId 可能更深,就像在對象數組中一樣。
ExModelC: {
_id: ObjectId,
someKey: [{
docFieldKey: string // if docAId, replace with docBId
otherKey: any
}]
}
我想找到所有名為“docFieldKey”的字段,檢查它們的值,如果是 docAId,則用 docBId 替換。 這樣做的最簡單方法是什么? 是否有一個貓鼬查詢可以完成繁重的工作?
注意:我預計需要定期替換系統中的文檔,因此我正在嘗試為任意 docFieldKey 制作此腳本,以便它可以重用。
是的,您可以為 mongo shell 編寫查詢。 在 mongo shell 上,它會運行得太快也太容易了。
查詢示例 -
db.loans.find({ _id: docA },function (DocAA) {
db.loans.find({ _id: docB },function (DocBB) {
print("DocAA: " + DocAA._id + "DocBB: " + DocBB._id);
db.loans.update({ _id: docA }, { $set: { _deleted: true } });
});
db.loans.remove({ _id: docB});
});
我最終在我們的 NodeJS 服務器上這樣做了。 要運行,只需調用“replaceDocument”。 如果人們覺得它有用,我可能會將其放入 npm 包中。 我還沒有在任何地方看到過這個功能。
let toReplace = null;
let replacement = null;
let searchKey = null;
function replaceReferencesInDoc(document) {
let mongooseUpdateObject = null;
function checkForSearchKey(anyType, path, currentKey) {
if (currentKey === searchKey && anyType + "" === toReplace + "") {
if (!mongooseUpdateObject) mongooseUpdateObject = {};
mongooseUpdateObject[path] = replacement;
} else if (typeof anyType === "object" && anyType !== null && !Array.isArray(anyType)) {
const keys = Object.keys(anyType);
for (let i = 0; i < keys.length; i += 1) {
checkForSearchKey(anyType[keys[i]], `${path}${path !== "" ? "." : ""}${keys[i]}`, keys[i]);
}
} else if (Array.isArray(anyType)) {
for (let i = 0; i < anyType.length; i += 1) {
checkForSearchKey(anyType[i], `${path}${path !== "" ? "." : ""}${i}`, i);
}
}
}
checkForSearchKey(document, "", "");
if (mongooseUpdateObject) {
console.log(`update object for ${document._id}`, mongooseUpdateObject);
}
return mongooseUpdateObject;
}
async function replaceReferencesInCollection(model) {
const allDocuments = await model.find().lean().exec();
const replacementPromises = [];
for (let j = 0; j < allDocuments.length; j += 1) {
const update = replaceReferencesInDoc(allDocuments[j]);
if (update) {
replacementPromises.push(
model.update({ _id: allDocuments[j]._id }, update).exec(),
);
}
}
await Promise.all(replacementPromises);
}
async function runReplaceDocument(toReplaceParam, replacementParam, searchParam, arrayOfModels) {
try {
toReplace = toReplaceParam;
replacement = replacementParam;
searchKey = searchParam;
const start = new Date().getTime();
console.log(`searching for ${searchKey} = ${toReplace} to replace with ${replacement}`);
console.log(" ");
for (let i = 0; i < arrayOfModels.length; i += 1) {
console.log(`--- checking collection ${arrayOfModels[i].collection.collectionName} ---`);
await replaceReferencesInCollection(arrayOfModels[i]); //eslint-disable-line
console.log(" ");
}
console.log(`replace took ${(new Date().getTime() - start) / 1000} seconds`);
} catch (err) {
console.log(err);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.