MongoDB:如何在集合中查找和替换ObjectId
我正在把两个文件合并成一个。为此,我想用对DocB的引用替换对DocA的所有引用 我希望对数据库中的所有文档和所有集合执行此操作。在集合/模型中,对此类文档的每个引用都使用相同的键“docFieldKey”。但是路径通常不同,因此有时位于顶层,有时位于文档中的对象数组中MongoDB:如何在集合中查找和替换ObjectId,mongodb,mongoose,Mongodb,Mongoose,我正在把两个文件合并成一个。为此,我想用对DocB的引用替换对DocA的所有引用 我希望对数据库中的所有文档和所有集合执行此操作。在集合/模型中,对此类文档的每个引用都使用相同的键“docFieldKey”。但是路径通常不同,因此有时位于顶层,有时位于文档中的对象数组中 ExModelA: { _id: ObjectId, docFieldKey: string // if docAId, replace with docBId } 对docA的引用可以在如下子字段中: ExMod
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。感谢您尝试解决此问题。但我认为我们彼此并不了解。我试着把问题弄清楚。