MongoDB: как найти и заменить ObjectId в коллекции - PullRequest
0 голосов
/ 27 января 2020

Я объединяю два документа в один. Для этого я хочу заменить все ссылки на DocA ссылками на DocB.

Я хочу сделать это для всех документов и всех коллекций в базе данных. Во всех коллекциях / моделях каждая ссылка на этот тип документа использует один и тот же ключ, «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. Какой самый простой способ сделать это? Есть ли запрос mon goose, который мог бы выполнить тяжелую работу?

Примечание: я ожидаю, что периодически потребуется замена документов в системе, поэтому я пытаюсь создать этот сценарий для произвольного docFieldKey, чтобы его можно было повторно использовать ,

Ответы [ 2 ]

0 голосов
/ 07 февраля 2020

Я закончил делать это на нашем 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);
  }
}
0 голосов
/ 27 января 2020

Да, вы можете написать запрос для оболочки go. В оболочке mon go она будет работать слишком быстро и легко.

Образец запроса -

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});
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...