簡體   English   中英

MongoDB:如何跨集合查找和替換 ObjectId

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM