添加具有增量整数的新元素/字段作为值

时间:2017-12-12 11:56:01

标签: vb.net mongodb

使用MongoimportCSV文件导入我的数据库后,我想为每个文档添加一个新字段或元素。并且,此新字段的每个数据是索引号加上2.

Dim documents = DB.GetCollection(Of BsonDocument)(collectionName).Find(filterSelectedDocuments).ToListAsync.Result


For Each doc in documents
    DB.GetCollection(Of BsonDocument)(collectionName).UpdateOneAsync(
        Builders(Of BsonDocument).Filter.Eq(Of ObjectId)("_id", doc.GetValue("_id").AsObjectId),
        Builders(Of BsonDocument).Update.Set(Of Integer)("increment.value", documents.IndexOf(doc) + 2).Wait()
Next

如果我要导入超过一百万的数据,是否有更好的方法来实现此目的,例如使用UpdateManyAsync

1 个答案:

答案 0 :(得分:1)

正如旁注:由于您到处都有Wait()Result,因此Async方法似乎不会产生太大的影响。感。此外,由于任何地方都没有.Sort(),因此您的逻辑显示有缺陷。因此,您无法保证退回文件的顺序。它是否被称为每个文档只是获得一种随机但唯一且不断增加的数字?

无论如何,为了加快速度,你真的想要修补你的CSV文件并编写增加的" increment.value"在导入之前直接进入它。这样,您就可以直接在MongoDB中获得价值,而无需再次查询和更新导入的数据。

如果这不是一个选项,您可以像这样优化您的代码:

  1. 只检索文档的_id - 这就是您所需要的全部内容,因为需要从MongoDB传输/反序列化的数据少得多,这将对您的.find()性能产生重大影响。< / LI>
  2. 迭代结果的Enumerable,而不是使用完全填充的列表。
  3. 使用批量写入以避免为每个文档反复连接到MongoDB,并使用分块刷新方法并刷新每1000个文档左右。
  4. 从理论上讲,您可以进一步使用多线程或yield语义来实现更好的流式传输。但是,这有点复杂,甚至可能不需要。
  5. 以下内容可以让您加快速度:

    ' just some cached values
    Dim filterDefinitionBuilder  = Builders(Of BsonDocument).Filter
    Dim updateDefinitionBuilder  = Builders(Of BsonDocument).Update
    Dim collection = DB.GetCollection(Of BsonDocument)(collectionName)
    
    ' load only _id field
    Dim documentIds = collection.Find(filterSelectedDocuments).Project(Function(doc) doc.GetValue("_id")).ToEnumerable()
    
    ' bulk write buffer (pre-initialized to size 1000 to avoid memory traffic upon array expansion)
    Dim updateModelsBuffer = new List(Of UpdateOneModel(Of BsonDocument))(1000)
    
    ' starting value for our update counter
    Dim i As Long = 2 
    
    For Each objectId In documentIds
        ' for every document we want one update command...
        ' ...that finds exactly one document identified by its _id field
        Dim filterDefinition  = filterDefinitionBuilder.Eq(Of ObjectId)("_id", objectId)
        ' ...and updates the "increment.value" with our running counter
        Dim updateDefinition  = updateDefinitionBuilder.Set(Of Integer)("increment.value", i)
    
        updateModelsBuffer.Add(New UpdateOneModel(Of BsonDocument)(filterDefinition, updateDefinition))
    
        ' every e.g. 1000 documents
        If updateModelsBuffer.Count = 1000
            ' we flush the contents to the database
            collection.BulkWrite(updateModelsBuffer)
            ' and we empty our buffer list
            updateModelsBuffer.Clear()
        End If
        i = i + 1
    Next
    
    ' flush left over commands that have not been written yet in case we do not have a multiple of 1000 documents
    collection.BulkWrite(updateModelsBuffer)