MongoDB:如何在集合中查找和替换ObjectId

MongoDB:如何在集合中查找和替换ObjectId,mongodb,mongoose,Mongodb,Mongoose,我正在把两个文件合并成一个。为此,我想用对DocB的引用替换对DocA的所有引用 我希望对数据库中的所有文档和所有集合执行此操作。在集合/模型中,对此类文档的每个引用都使用相同的键“docFieldKey”。但是路径通常不同,因此有时位于顶层,有时位于文档中的对象数组中 ExModelA: { _id: ObjectId, docFieldKey: string // if docAId, replace with docBId } 对docA的引用可以在如下子字段中: ExMod

我正在把两个文件合并成一个。为此,我想用对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);
  }
}
让toReplace=null;
让替换=null;
让searchKey=null;
函数replaceReferencesInDoc(文档){
让mongooseUpdateObject=null;
搜索键的功能检查(任意类型、路径、当前键){
如果(currentKey==searchKey&&anyType+“”==toReplace+“”){
如果(!mongooseUpdateObject)mongooseUpdateObject={};
mongooseUpdateObject[path]=替换;
}else if(typeof anyType==“object”&&anyType!==null&&&!Array.isArray(anyType)){
常量键=Object.keys(anyType);
for(设i=0;i
是否合并两个文档或集合?两个文档。DocA正在被DocB取代。我需要将所有对DocA的ObjectId引用替换为对DocB的ObjectId引用,然后我将删除DocA。请稍候。我正在编辑我的ans。看起来它将删除所有引用DocA的文档。我想用DocB替换那些引用。现在检查。这是对u的引用而不是查询。在此查询中,请根据您的要求编写$set。感谢您尝试解决此问题。但我认为我们彼此并不了解。我试着把问题弄清楚。