我是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专家能否对此深入了解?
谢谢!
答案 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。