我是 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
会更简单,它为您包装了复杂性:
using (var cursor = await collection.FindAsync(filter))
{
await cursor.ForEachAsync(document =>
{
// process document
count++;
}
}
查看 ForEachAsync
来源 here .
如源代码所示,ForEachAsync
获取游标的所有权并为您处理它,因此您也可以根据需要省略自己的using
。
关于c# - MongoDB C# 驱动程序 IAsyncCursor<BsonDocument> 行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40007258/