MongoDB C#驱动程序IAsyncCursor <bsondocument>行为?

时间:2016-10-12 19:57:05

标签: c# mongodb

我是MongoDB的新手(以及它的dotnet核心C#驱动程序),我对IAsyncCursor行为有以下问题:

从官方文档: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++;
        }
    }
}

然而,似乎要获得&#34;当前&#34;批量返回的文档,while循环首先&#34; MoveNextAsync&#34;,&#34; MoveNextAsync&#34;跳过&#34;当前&#34;批量?或者逻辑上,以下修改过的代码片段会更有意义吗?

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())
}

我的理解是光标应该从指向&#34;当前&#34;开始。批量已经(如果有的话),我应该首先处理&#34;当前&#34;批次是,然后移动到下一批文件,如果有的话。

但是对于我可以在网上找到的所有来源,似乎迭代总是做&#34; MoveNext&#34;首先,然后处理批处理 - 这给我的印象是FindAsync返回的IAsyncCursor开始指向实际&#34;当前&#34;之前的位置。 (或第一批)文件,&#34; MoveNext&#34;必须首先调用将光标移动到指向实际电流。

从编码的角度来看,调用&#34; MoveNext&#34;首先使while循环更加一致,因此我自己的代码片段不必(冗余地)检查&#34; current&#34;的有效性。在&#34;做&#34;。

的内部

然而,我确实发现&#34; IAsyncCursor.First()&#34;确实会返回&#34;首先&#34;文件 - 我现在猜测&#34; First()&#34;方法实际上做了一个&#34; MoveNext&#34;在内部,并返回&#34;当前&#34;的第一个文件。批次。

此外,由于我正在使用&#34; FindAsync&#34;,如果根据我的过滤器找不到文档,则返回的IAsyncCursor&#34; null&#34;或&#34; MoveNext&#34;会返回虚假?我可以假设FindAsync返回的IAsyncCursor始终是一个有效的对象,所以我不必过度检查null,只需要检查&#34; MoveNext()&#34;或&#34; First()&#34;?

MongoDB专家能否对此深入了解?

谢谢!

2 个答案:

答案 0 :(得分:1)

第一个代码示例是正确的,不会跳过第一个代码。但是,如果要显式控制获取批次,则只需直接使用MoveNextAsync

否则,使用ForEachAsync可以更简单地为您包装复杂性:

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

请参阅ForEachAsync来源here

如源代码所示,ForEachAsync获取光标的所有权并为您处置,因此如果您愿意,也可以省略自己的using

答案 1 :(得分:1)

所以从我的所有测试和我在网上找到的来源看来,我的原始观察结果似乎是正确的,因为FindAsync方法返回的IAsyncCursor最初是在中性状态下启动的(“当前”似乎为空),必须首先调用MoveNext(Async)以使其移动到第一批“Current”将包含第一批文档 - 我还观察到一个不存在的查找结果,MoveNext将使光标具有“Current” “ null,但是Current.Count()将返回0,这意味着即使MoveNext成功,但仍然没有此批处理中的文档 - 这在某种程度上暴露了API设计的一致性问题 - 如果“MoveNext”返回false以指示没有更多文档,或者在成功的“MoveNext”之后,“Current”应为null以指示没有文档,或者“Current”应为非null,则Current.Count ()== 0表示没有文件?现在我正在检查所有这三个条件,以确保我的代码是安全的,而我认为“MoveNext”已经返回false,表示没有其他文档是最直观的API。