我在向user's 集合的所有記錄中添加另一個欄位時遇到了困難,其中包含每個檔案的值。我熟悉使用$setwithdb.model.updateMany和$addFields聚合管道,我過去曾使用它們來解決問題,在這種情況下,我必須在添加值之前執行一些邏輯/計算,這就是我的問題所在。
說,我有這樣的架構:
{
"users": [
{
"wallets": {...},
"avatar": "",
"isVerified": false,
"suspended": false,
"country": "Nigeria",
"_id": "123",
"resetPasswordToken": "",
"email": "[email protected]",
"phone": "08012398743",
"name": "Agbakwuru Nnaemeka Kennedy ",
"role": "user",
},
{...}
}
我想添加一個新欄位phoneNumber,它將采用現有欄位的值phone,但在添加之前,我想在其上運行一個邏輯,因為某些電話值有空格,其中大多數沒有正確格式化,我想在將國家代碼phone添加到新phoneNumber欄位之前將其添加到值中。
我能夠使用 Mongoosedb.mode.aggregate方法的游標和$match過濾器完成此操作,并使用聚合$addFields管道將欄位添加到每個檔案,這證明需要花費大量時間,我不得不停止操作,因為它花費太多是時候跑了。
我想相信有更好的方法,拜托,我將不勝感激。
編輯:
這是我正在使用的聚合:
const userCursor = User.aggregate([{$match: {phone: {$exists: true}}}]);
for await (const doc of userCursor) {
await User.findByIdAndUpdate(doc._id, {$set: {
phoneNumber: convertPhoneNumber({phoneNumber: doc.phone.replace(/\s /g, "")})}
});
}
這convertPhoneNumber是我在實用程式中定義的一種輔助方法,用于將國家/地區交易代碼添加到電話號碼中。
uj5u.com熱心網友回復:
我會嘗試直接在mongo命令列或 Robo3T 中運行這樣的腳本:
db.getCollection("users").find({}).forEach( doc => {
doc.users.forEach( user => {
// do your logic here
let phoneNumber = "12345";
phoneNumber = " 007" phoneNumber;
user.phoneNumber = phoneNumber;
})
db.users.save(doc);
})
處理 30 萬多個檔案仍然需要一段時間,但請給它幾分鐘時間。
uj5u.com熱心網友回復:
您可以$function在資料庫中使用和呼叫該 javascript 代碼。
這需要 >=MongoDB 4.4
db.Users.update(
{phone: {$exists: true}},
[{$set: {phoneNumber:
{
"$function": {
"body": YOUR_convertPhoneNumber_FUNCTION_DEF,
"args": ["$phoneNumber"],
"lang": "js"
}
}])
此外,如果 convertPhoneNumber 的代碼可以使用聚合運算子在 MongodBD 中撰寫,您也可以避免使用 javascript。
以上是管道更新,更新時我們可以使用所有聚合運算子。
編輯
如果$functionmongoose有問題,或者 nodejs 驅動程式方法有管道更新問題,你也可以這樣做。
db.runCommand(
{
update: "yourCollectionName",
updates: [
{
q: {phone: {$exists: true}},
u:
[{$set: {phoneNumber:
{
"$function": {
"body": YOUR_convertPhoneNumber_FUNCTION_DEF,
"args": ["$phoneNumber"],
"lang": "js"
}
}],
multi: true
}
],
ordered: false
}
)
uj5u.com熱心網友回復:
您可以嘗試Bulk Operation,這會分批更新 1000 個檔案的集合:
var bulkOperations = [];
db.getCollection("users").find({}).forEach(doc => {
doc.users.forEach(user => {
user.phoneNumber = convertPhoneNumber({phoneNumber: user.phone.replace(/\s /g, "")});
})
bulkOperations.push({
updateOne: {
filter: { id: doc._id },
update: { $set: { users: doc.users } }
}
});
if (bulkOperations.length > 1000) {
db.getCollection("users").bulkWrite(bulkOperations, { ordered: false });
bulkOperations = [];
}
})
if (bulkOperations.length > 0)
db.getCollection("users").bulkWrite(bulkOperations, { ordered: false });
uj5u.com熱心網友回復:
的幫助下@Jeremy Thille的答案在這里,我能夠用MongoDB的指南針來解決它mongo與下面的代碼片段的命令列。
db.users.find({phone: {$exists: true}}).forEach( user => {
const phone = user.phone.replace(/\s /g, "");
const phoneNumber = ` 234${phone.slice((phone.length - 10))}`;
db.users.updateOne({_id: user._id}, {$set: {phoneNumber}});
})
缺點是更新 300K 檔案需要 10-15 分鐘,這與我最初的實作相比,這是一個顯著的改進,我最初的實作只需要花費一天的時間來更新幾萬個檔案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/336684.html
標籤:javascript 节点.js MongoDB 猫鼬 nosql
上一篇:渲染用戶IDExpressJS
