我試圖遷移約 600k 檔案的大型 MongoDB,如下所示:
for await (const doc of db.collection('collection').find({
legacyProp: { $exists: true },
})) {
// additional data fetching from separate collections here
const newPropValue = await fetchNewPropValue(doc._id)
await db.collection('collection').findOneAndUpdate({ _id: doc._id }, [{ $set: { newProp: newPropValue } }, { $unset: ['legacyProp'] }])
}
}
遷移腳本完成后,資料仍在更新大約 30 分鐘左右。我通過計算包含legacyProp屬性的檔案的檔案數量得出了這一結論:
db.collection.countDocuments({ legacyProp: { $exists: true } })
隨后的通話中減少了。過了一段時間,更新停止了,包含 legacy prop 的檔案的最終檔案數約為 300k,因此更新無聲無息地失敗,導致資料丟失。我很好奇到底發生了什么,最重要的是,如何在不丟失任何資料的情況下更新大型 MongoDB 集合?請記住,在每次更新操作之前都會涉及額外的資料獲取。
uj5u.com熱心網友回復:
我的第一次嘗試是fetchNewPropValue()在聚合管道中構建函式。
查看聚合管道運算子
如果這是不可能的,那么您可以嘗試將所有 newPropValue 放入陣列并像這樣使用它。600k 屬性應該很容易放入您的 RAM。
const newPropValues = await fetchNewPropValue() // getting all new properties as array [{_id: ..., val: ...}, {_id: ..., val: ...}, ...]
db.getCollection('collection').updateMany(
{ legacyProp: { $exists: true } },
[
{
$set: {
newProp: {
$first: {
$filter: { input: newPropValues, cond: { $eq: ["$_id", "$$this._id"] } }
}
}
}
},
{ $set: { legacyProp: "$$REMOVE", newProp: "$$newProp.val" } }
]
)
或者你可以試試 bulkWrite:
let bulkOperations = []
db.getCollection('collection').find({ legacyProp: { $exists: true } }).forEach(doc => {
const newPropValue = await fetchNewPropValue(doc._id);
bulkOperations.push({
updateOne: {
filter: { _id: doc._id },
update: {
$set: { newProp: newPropValue },
$unset: { legacyProp: "" }
}
}
});
if (bulkOperations.length > 10000) {
db.getCollection('collection').bulkWrite(bulkOperations, { ordered: false });
bulkOperations = [];
}
})
if (bulkOperations.length > 0)
db.getCollection('collection').bulkWrite(bulkOperations, { ordered: false })
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/435818.html
