2016-10-12 19 views
1

我是新來的MongoDB(及其DOTNET核心C#驅動程序),我有關於IAsyncCursor行爲以下問題:MongoDB C#驅動程序IAsyncCursor <BsonDocument>行爲?

從官方文檔:https://docs.mongodb.com/getting-started/csharp/query/,似乎通過IAsyncCursor迭代的推薦方法是:

var collection = _database.GetCollection<BsonDocument>("restaurants"); 
var filter = new BsonDocument(); 
var count = 0; 
using (var cursor = await collection.FindAsync(filter)) 
{ 
    while (await cursor.MoveNextAsync()) 
    { 
     var batch = cursor.Current; 
     foreach (var document in batch) 
     { 
      // process document 
      count++; 
     } 
    } 
} 

然而,似乎得到了「目前」批返回的文件,while循環第一「MoveNextAsync」,確實「MoveNextAsync」跳過「當前」批次?或者從邏輯上講,以下修改過的代碼片段會更有意義嗎?

var collection = _database.GetCollection<BsonDocument>("restaurants"); 
var filter = new BsonDocument(); 
var count = 0; 
using (var cursor = await collection.FindAsync(filter)) 
{ 
    do 
    { 
     if (cursor.Current != null) 
     { 
      var batch = cursor.Current; 
      foreach (var document in batch) 
      { 
       // process document 
       count++; 
      } 
     } 
    } 
    while (await cursor.MoveNextAsync()) 
} 

我的理解是,光標應該指向「當前」批次已經(如果有的話)開始,我就什麼「當前」批先工作,然後移動到下一個批次的文件,如果有的話。

但是對於我可以在網上找到的所有資源,似乎迭代總是首先執行「MoveNext」,然後處理批處理 - 這給我的印象是由FindAsync返回的IAsyncCursor開始指向一個位置在實際的「當前」(或第一批)文檔之前,並且需要首先調用「MoveNext」以將光標移動到指向實際電流。

從編碼的角度來看,調用「MoveNext」首先使得while循環更加一致,因此我自己的代碼片段不必(冗餘地)檢查「當前」做」。我發現「IAsyncCursor.First()」確實返回了「第一個」文檔 - 我現在猜測「First()」方法實際上是在內部執行「MoveNext」,並返回第一個「當前」批次的文件。

此外,因爲我使用的是「FindAsync」,並且如果找不到基於我的過濾器的文檔,返回的IAsyncCursor「null」還是「MoveNext」將返回false?我可以假設FindAsync返回的IAsyncCursor始終是一個有效的對象,所以我不必過於檢查null,只需檢查「MoveNext()」或「First()」的返回值?

您可以讓MongoDB專家對此有所瞭解嗎?

謝謝!

回答

1

因此,從我在網上找到的所有測試和源代碼看來,我最初的觀察結果是正確的,即由FindAsync方法返回的IAsyncCursor最初以中性狀態啓動(「Current」似乎爲null),必須首先調用MoveNext(Async)才能將其移至第一批,即「當前」將包含第一批文檔 - 我還觀察到不存在查找結果,MoveNext將使光標具有「當前「不是 null,但Current.Count()將返回0,這意味着即使MoveNext成功,但此批處理中仍然沒有文檔 - 這在某種程度上暴露了API設計一致性的問題 - 」MoveNext「返回false表示沒有更多文檔,或者在成功的「MoveNext」之後,應該將「Current」設置爲null以指示e表示沒有文檔,或者「Current」爲非null,則Current.Count()== 0表示沒有文檔?現在我正在檢查所有三個條件,以確保我的代碼安全,而我認爲使「MoveNext」已經返回false以表示沒有其他文檔將是最直觀的API使用。

1

第一個代碼示例是正確的,不會跳過第一批。但是,如果要明確控制批次取批,您只需直接使用MoveNextAsync即可。

否則,它是簡單的使用ForEachAsync它包裝的複雜性給你:

using (var cursor = await collection.FindAsync(filter)) 
{ 
    await cursor.ForEachAsync(document => 
    { 
     // process document 
     count++; 
    } 
} 

ForEachAsynchere

如源代碼所示,ForEachAsync取得了遊標的所有權併爲您處置,因此如果您願意,您也可以省略自己的using

+0

感謝您的回答,我知道並且大部分都在使用ForEachAsync。但是,我的問題更多地是關於MoveNext的行爲,不完全是我應該使用ForEachAsync來替換示例代碼中的vanilla while循環。或者你可以更具體地瞭解MoveNext的行爲,我的問題更準確地關注? – Dejavu

+0

@Dejavu沒問題,你說你是MongoDB和驅動程序的新手,所以我認爲你可能會讓事情比他們需要的更難。 – JohnnyHK