我对mongodb(及其dotnet core 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开始指向实际“当前”(或第一批)文档之前的位置,a需要首先调用nd“moveNext”来移动光标以指向实际电流。
从编码的角度来看,首先调用“moveNext”会使while循环更加一致,因此我自己的代码片段不必(冗余地)检查“do”主体中“current”的有效性。
但是,我发现“iasynccursor.first()”确实返回了“first”文档——我现在猜“first()”方法实际上在内部执行了“moveNext”,并返回了“current”批处理的第一个文档。
另外,由于我使用的是“findasync”,如果根据我的过滤器找不到文档,那么返回的iasynccursor是“null”还是“moveNext”将返回false?我可以假设findasync返回的iasyncursor总是一个有效的对象,所以我不必过度检查null,只需要检查“moveNext()”或“first()”的返回吗?
你能不能让MongoDB的专家们来谈谈你对此的看法?
谢谢!
最佳答案
第一个代码示例是正确的,不会跳过第一批代码。但是,如果希望显式控制获取批处理,则只需直接使用MoveNextAsync
。
否则,使用ForEachAsync
就更简单了,它为您包装了这种复杂性:
using (var cursor = await collection.FindAsync(filter))
{
await cursor.ForEachAsync(document =>
{
// process document
count++;
}
}
参见
ForEachAsync
源here。如源代码中所示,
ForEachAsync
取得光标的所有权并为您处置它,因此如果您愿意,还可以省略自己的using
。