2017-12-12 1 views
0

Mongoimport을 사용하여 데이터베이스에 CSV 파일을 가져온 후 문서 당 새 필드 또는 요소를 추가하려고합니다. 내가 가져올 데이터의 백만 이상이있는 경우 그리고,이 새로운 분야에 대한 당 데이터가 인덱스 번호 플러스 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

보조 노트와 마찬가지로 : 및 Result이 모든 지역에 있으므로 Async 메소드는 엄청난 의미가없는 것처럼 보입니다. 또한 .Sort()이 없기 때문에 논리에 결함이있는 것으로 보입니다. 따라서 반환 된 문서의 순서에 대해서는 아무런 보장이 없습니다. 모든 문서가 무작위로 그러나 유일하고 증가하는 숫자의 종류를 부여받습니다.

어쨌든이 작업을 더 빨리 수행하려면 CSV 파일을 패치하고 가져 오기 전에 증가하는 "increment.value"필드를 직접 써야합니다. 이렇게하면 MongoDB에 직접적으로 가치를 부여 할 수 있으며 가져온 데이터를 다시 쿼리하고 업데이트 할 필요가 없습니다.

이이 같은 코드를 최적화 할 수있는 옵션이없는 경우 :

  1. 만 문서의 _id 검색은 - 그게 당신이 필요로하는 모든 그리고 그것은 majorly 훨씬 덜 데이터 요구 이후 .find() perfomance에 영향을 미칠 것이다 MongoDB에서 양도/역 직렬화.
  2. 완전히 채워진 목록을 사용하는 대신 결과의 Enumerable을 반복합니다.
  3. 대량 기록을 사용하여 모든 문서에 대해 MongoDB에 계속 연결되는 것을 피하고 청크 방식으로 플러시 방식을 사용하고 1000 개 정도의 문서를 모두 플러시합니다.
  4. 이론적으로는 더 나은 스트리밍을 위해 멀티 스레딩 또는 yield 의미 체계를 사용하여 더 나아갈 수 있습니다. 그러나 조금 복잡해지며 필요하지 않을 수도 있습니다.

다음은 당신이 빠른 이미 가야한다 :

' 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) 
+0

내가 증가 값으로 새 열을 추가하여'CSV' 파일을 업데이트했습니다. 그러나 [문제] (https://stackoverflow.com/questions/47710358/new-column-row-data-for-csv)는 줄 바꿈으로 인한 값입니다. 나는 모든 라인을 읽고 그 라인의 인덱스를 증가 값으로 사용하고있다. 그러나, 새로운 라인이 있기 때문에, 그것은 나에게 증가하지 않는 값을줍니다. 나는'\ r'과'\ n'을 빈 문자열로 바꾸려고했지만 아무 쓸모가 없습니다. 따라서 두 번째 옵션은 위의 코드입니다. 최근에 가져온 문서를 호출하고 하나씩 업데이트합니다. – Hobert

+0

증가 값이있는 새 열을 추가하도록 사용자에게 말하고 싶지 않습니다. 'Result'와'Wait'을 넣지 않으면, 코드가 붉은 선/에러를 갖습니다. 답변 해 주셔서 감사합니다. 나는'BulkWrite'에 대해 생각하고 있었지만 코드로 시작하는 방법을 모른다. – Hobert

관련 문제