[英]MongoDB C# driver IAsyncCursor<BsonDocument> behavior?
我是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++;
}
}
}
但是,似乎要获取返回的文档的“当前”批次,而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循环更加一致,因此我自己的代码段不必(冗余地)检查“ do”体内“ current”的有效性。
但是,我确实发现“ IAsyncCursor.First()”确实返回了“第一个”文档-现在,我猜测“ First()”方法实际上在内部进行了“ MoveNext”操作,并返回了“当前”批次。
另外,当我使用“ FindAsync”时,如果找不到基于我的过滤器的文档,返回的IAsyncCursor是否为“ null”或“ MoveNext”是否将返回false? 我是否可以假定FindAsync返回的IAsyncCursor始终是有效对象,所以我不必过多地检查null,而只需检查“ MoveNext()”或“ First()”的返回值?
您能不能请MongoDB专家对此发表见解?
谢谢!
第一个代码示例正确,并且不会跳过第一批。 但是,如果要显式控制获取批处理,则仅需要直接使用MoveNextAsync
。
否则,使用ForEachAsync
会更简单, ForEachAsync
它为您带来了这种复杂性:
using (var cursor = await collection.FindAsync(filter))
{
await cursor.ForEachAsync(document =>
{
// process document
count++;
}
}
在此处查看ForEachAsync
源。
如源代码所示, ForEachAsync
获取光标的所有权并为您处理它,因此您也可以根据需要省略自己的using
。
因此,从我的所有测试和在网上找到的资源来看,似乎我的原始观察是正确的,即FindAsync方法返回的IAsyncCursor最初以中立状态(“当前”似乎为空)开始,即MoveNext(Async )必须先调用,以使其移动到“当前”将包含第一批文档的第一批-我还观察到不存在的查找结果,MoveNext将使光标的“当前” 不为 null ,但Current.Count()将返回0,这意味着即使MoveNext成功执行,但该批次中也没有文档-这以某种方式暴露了API设计一致性的问题-“ MoveNext”应该返回false表示存在没有更多文档,或者在成功执行“ MoveNext”之后,如果“ Current”为null表示没有文档,或者“ Current”为非null,则Current.Count()== 0表示没有文档文件? 现在,我正在检查所有三个条件,以确保我的代码是安全的,同时我认为使“ MoveNext”已经返回false表示没有其他文档将是最直观的API。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.