我需要优化 mongo 集合更新

Posted

技术标签:

【中文标题】我需要优化 mongo 集合更新【英文标题】:I need to optimize a mongo collection update 【发布时间】:2021-10-04 14:48:18 【问题描述】:

我需要编写一个脚本,将新字段写入我的集合中的嵌入对象。 假设我的集合名称是 Proposition,它包含 100000 个文档,它看起来像这样:

[
"Id": "1111",
"name":"Name",
"products": [

    "productId": "P1",
,
    "productId": "P2",
]
]

我的目标是为每个产品添加一个名为 parent 的新字段:

[
"Id": "1111",
"name":"Name",
"products": [

    "productId": "P1",
    **"parent": "parent1"**
,
    "productId": "P2",
    **"parent": "Parent2"**
]
]

我需要从另一个名为 Products 的集合中获取父字段,看起来像这样

[
   "productId": "P1",
   "parent": "parent1"
,

    "productId": "P2",
    "parent": "Parent2"
]

因此脚本需要从 Product 集合中获取 productId 和与之相关的父级,然后通过添加父字段来更新包含该产品的命题集合。

我为知道而编写的脚本:

db.Products.find()
.toArray()
.forEach(function(product)
        updateWithParentID(product.productId,product.parent)
   )
function updateWithParentID(prosuctId,parent)
db.Propositions.updateOne(
    'products.productId':prosuctId,
    $set:"products.$.parent":parent)

它可以工作,但不幸的是它需要很多时间,所以我想知道是否有更好更有效的方法来执行此更新

谢谢。

【问题讨论】:

我建议使用批量写入操作以获得更好的性能。此外,对于您的更新,您需要掌握使用 arrayFilters 进行有针对性的更新,以便将您的详细信息嵌入到提案集合中。 【参考方案1】:

我建议使用 bulkWrite 功能。这将通过消除每次更新往返的大部分网络延迟来减少总体时间...

var batch=[];

db.Products.find().toArray().forEach(function(product) 
    batch.push(
        
            updateOne: 
                "filter":  "products.productId": product.productId ,
                "update":  "$set":  "products.$.parent": product.parent  
            
        
    );
);

db.Propositions.bulkWrite(batch,  ordered: false  );

就准确性而言,您没有提供太多数据进行测试。您可能会发现需要使用 arrayFilters。

【讨论】:

非常感谢您的帮助,现在使用 bulkWrite 更新需要不到 5 秒,而之前需要 60 秒

以上是关于我需要优化 mongo 集合更新的主要内容,如果未能解决你的问题,请参考以下文章

Mongo - 从对象更新集合的每个文档

在 Mongo 集合中更新数组中的一条记录

当我们从 Mongo 控制台更新集合时,Meteor Apollo 没有更新 UI

Mongo - 更新文档时使用另一个字段的结果更新一个字段

流星集合不更新客户端上的订阅

根据同一数组中另一个元素满足的条件更新 mongo 集合中数组的元素