簡體   English   中英

MongoDB 使用來自另一個集合的查詢結果更新集合中的所有記錄

[英]MongoDB updating all records in a collection with the results of query from another collection

我有大約 40k 條記錄要更新,每條記錄都從查詢另一個集合中獲取數據。
我有一個現有的查詢來執行此操作,但它運行了一個多小時。 它通常斷開連接,然后我再次運行它。
我認為有更好的方法可以做到這一點,我只是 mongodb 的菜鳥,這個解決方案有效,但我對執行速度不滿意。
也許您有更好或更快的解決方案。

為了更好地說明數據,請參見下圖:

帳戶

[
  {
    "_id": ObjectId("AC101"),
    "emails":null,
    "name":"Account 101",
    ...
  },
  {
    "_id": ObjectId("AC102"),
    "emails":null,
    "name":"Account 102",
    ...
  },
  {
    "_id": ObjectId("AC103"),
    "emails":null,
    "name":"Account 103",
    ...
  },
  ...
]

account_contacts

[
  {
    "_id": Object("ACC001"),
    "account": {
        "$ref" : "account",
        "$id" : ObjectId("AC101")
    },
    "email":"acc001@test.com",
    "name":"Contact 001",
    ...
  },
  {
    "_id": Object("ACC002"),
    "account": {
        "$ref" : "account",
        "$id" : ObjectId("AC102")
    },
    "email":"acc002@test.com",
    "name":"Contact 002",
    ...
  },
  {
    "_id": Object("ACC003"),
    "account": {
        "$ref" : "account",
        "$id" : ObjectId("AC103")
    },
    "email":"acc003@test.com",
    "name":"Contact 003",
    ...
  },
  {
    "_id": Object("ACC004"),
    "account": {
        "$ref" : "account",
        "$id" : ObjectId("AC103")
    },
    "email":"acc004@test.com",
    "name":"Contact 004",
    ...
  },
  {
    "_id": Object("ACC005"),
    "account": {
        "$ref" : "account",
        "$id" : ObjectId("AC103")
    },
    "email":"acc005@test.com",
    "name":"Contact 005",
    ...
  },
  ...
]

詢問:

db.getCollection('accounts').find({ 'emails':{ $eq:null } }).forEach(p => {
    const emails = [];
    db.getCollection('account_contacts').find({"account.$id": p._id}).forEach(c => {
        emails.push(c.email);
    });
    db.getCollection('accounts').updateOne({"_id": p._id}, {$set: {"emails": emails}});
});

我有一個過濾器,只獲取帶有 null emails的帳戶,因此如果它出現超時錯誤(1 小時)......我只需重新運行腳本,它就會處理帶有 null 電子郵件的帳戶。

目前,我對如何改進查詢一無所知......但我知道這不是這種情況的最佳解決方案,因為它需要一個多小時。

更新:

雖然我仍然無法使聚合/查找方法起作用,但我確實嘗試在 mongo 控制台中運行舊腳本,我之前運行過它並在我的 ID 中執行了一個多小時......如果你直接在 mongo 控制台中運行它,它只需要 12-14 分鍾,這還不錯。

這就是我現在所做的,但我仍然想將我的腳本轉換為使用聚合。

TIA

使用 MongoDB 4.2,如果您願意使用臨時集合,則可以避免將文檔拉到客戶端。

使用聚合將所有文檔與 null email 匹配,僅提取 _id 並將其存儲在臨時集合中。 請注意,如果您在{emails:1, _id:1}上有一個索引,它將簡化這部分。 您可能希望以程序方式生成臨時集合名稱,這樣它就不會為連續運行使用相同的名稱。

db.accounts.aggregate([
    {$match: {emails: null}},
    {$project: {_id: 1}},
    {$out: "temporary_null_email_collection"}
])

然后聚合臨時集合,從 account_contacts 集合中查找 email,去掉任何無關字段,並將結果與 accounts 集合合並回來。

db.temporary_null_email_collection.aggregate([
    {$lookup:{
         from: "account_contacts",
         localField: "_id",
         foreignField: "$id", // verify this field name is correct
         as: contacts
    }},
    {$project: {
          _id: 1,
          emails: "$contacts.emails"
    }},
    {$merge: "accounts"}
])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM