简体   繁体   English

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

[英]MongoDB C# driver IAsyncCursor<BsonDocument> behavior?

I'm new to MongoDB (and its dotnet core C# driver), and I have the following question regarding the IAsyncCursor behavior: 我是MongoDB(及其dotnet核心C#驱动程序)的新手,关于IAsyncCursor行为,我有以下问题:

From the official documentation: https://docs.mongodb.com/getting-started/csharp/query/ , it seems that the recommended way of iterating through the IAsyncCursor is: 从官方文档: 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++;
        }
    }
}

However, it seems that to get the "current" batch of the returned documents, the while loop first "MoveNextAsync", does "MoveNextAsync" skips the "current" batch? 但是,似乎要获取返回的文档的“当前”批次,而while循环首先显示“ MoveNextAsync”,“ MoveNextAsync”是否跳过“当前”批次? Or logically, would the following modified code snippet makes more sense? 或者从逻辑上讲,以下修改后的代码片段更有意义吗?

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

My understanding is that the cursor should start by pointing to the "current" batch already (if any), and I should first work on whatever the "current" batch is, and then move to the next batch of documents, if any. 我的理解是,游标应该从已经指向“当前”批次(如果有)开始,并且我应该首先处理“当前”批次是什么,然后再移至下一批文档(如果有)。

But for all the sources I can find online, it seems the iteration always do "MoveNext" first, then work on the batch - this gives me the impression that the IAsyncCursor as returned by FindAsync starts off pointing to a position one prior to the actual "current" (or first) batch of the documents, and "MoveNext" is necessary to be called first to move the cursor to point to the actual current. 但是对于我可以在网上找到的所有资源,似乎迭代总是先执行“ MoveNext”,然后再进行批处理-这给我的印象是FindAsync返回的IAsyncCursor开始指向实际位置之前的位置。必须先调用“当前”(或第一批)文档,然后首先调用“ MoveNext”才能将光标移到实际当前位置。

From the coding point of view, calling "MoveNext" first makes the while loop more consistent, so my own code snippet doesn't have to (redundantly) check for the validity of the "current" inside the body of "do". 从编码的角度来看,首先调用“ MoveNext”可以使while循环更加一致,因此我自己的代码段不必(冗余地)检查“ do”体内“ current”的有效性。

However, I do find that "IAsyncCursor.First()" does return the "first" document - I'm guessing now that the "First()" method actually does a "MoveNext" internally, and returns the first document of the "current" batch. 但是,我确实发现“ IAsyncCursor.First()”确实返回了“第一个”文档-现在,我猜测“ First()”方法实际上在内部进行了“ MoveNext”操作,并返回了“当前”批次。

Also, as I'm using "FindAsync", and if the document is not found based on my filter, is the returned IAsyncCursor "null" or "MoveNext" will return false? 另外,当我使用“ FindAsync”时,如果找不到基于我的过滤器的文档,返回的IAsyncCursor是否为“ null”或“ MoveNext”是否将返回false? Can I assume that IAsyncCursor as returned by FindAsync is always a valid object, so I don't have to excessively check for null, and only need to check the return of "MoveNext()" or "First()"? 我是否可以假定FindAsync返回的IAsyncCursor始终是有效对象,所以我不必过多地检查null,而只需检查“ MoveNext()”或“ First()”的返回值?

Could you MongoDB experts shed your insights into this? 您能不能请MongoDB专家对此发表见解?

Thanks! 谢谢!

The first code sample is correct and doesn't skip the first batch. 第一个代码示例正确,并且不会跳过第一批。 However, you only need to directly use MoveNextAsync if you want explicit control of fetching batches. 但是,如果要显式控制获取批处理,则仅需要直接使用MoveNextAsync

Otherwise, it's simpler to use ForEachAsync which wraps that complexity for you: 否则,使用ForEachAsync会更简单, ForEachAsync它为您带来了这种复杂性:

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

See the ForEachAsync source here . 此处查看ForEachAsync源。

As shown in the source, ForEachAsync takes ownership of the cursor and disposes it for you so you can also omit your own using if you like. 如源代码所示, ForEachAsync获取光标的所有权并为您处理它,因此您也可以根据需要省略自己的using

So from all my testing and the sources I have found online, it seems that my original observation was correct that the IAsyncCursor as returned by the FindAsync method initially starts in a neutral state ("Current" seems to be null), that MoveNext(Async) has to be called first to make it move to the first batch that "Current" will then contain the first batch of documents - I also observed for a non-existing find result, MoveNext will make the cursor to have "Current" not null, but Current.Count() would return 0, meaning even though MoveNext succeeded, but still there are no documents in this batch - this somehow exposes a problem with the consistency of the API design - Should "MoveNext" return false to indicate there are no more documents, or after a successful "MoveNext", should "Current" be null to indicate that there are no documents, or should "Current" be non-null, then Current.Count() == 0 indicates that there are no documents? 因此,从我的所有测试和在网上找到的资源来看,似乎我的原始观察是正确的,即FindAsync方法返回的IAsyncCursor最初以中立状态(“当前”似乎为空)开始,即MoveNext(Async )必须先调用,以使其移动到“当前”将包含第一批文档的第一批-我还观察到不存在的查找结果,MoveNext将使光标的“当前” 不为 null ,但Current.Count()将返回0,这意味着即使MoveNext成功执行,但该批次中也没有文档-这以某种方式暴露了API设计一致性的问题-“ MoveNext”应该返回false表示存在没有更多文档,或者在成功执行“ MoveNext”之后,如果“ Current”为null表示没有文档,或者“ Current”为非null,则Current.Count()== 0表示没有文档文件? Now I'm checking all the three conditions to make sure that my code is safe, while I think making "MoveNext" to already return false to indicate no further documents would be the most intuitive API to use. 现在,我正在检查所有三个条件,以确保我的代码是安全的,同时我认为使“ MoveNext”已经返回false表示没有其他文档将是最直观的API。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 MongoDB C#驱动程序Mock方法返回IAsyncCursor - MongoDB C# driver Mock method that returns IAsyncCursor 如何使用 IAsyncCursor 与 mongodb c# 驱动程序进行迭代? - How is an IAsyncCursor used for iteration with the mongodb c# driver? C# MongoDB IAsyncCursor 详解 - C# MongoDB IAsyncCursor Explain 如何使用 Mongodb C# 驱动程序检查 BsonDocument 中是否存在密钥? - How to check if key exists in BsonDocument or not using Mongodb C# driver? c#mongodb BsonDocument数组 - c# mongodb BsonDocument array C# MongoDB Driver 2.0 将“严格模式”Json 转换为“mongo shell 模式”BsonDocument - C# MongoDB Driver 2.0 converting "strict mode" Json to "mongo shell mode" BsonDocument 如何使用 BsonDocument C# .NET 驱动程序在 MongoDB 中将多个投影和查找作为聚合执行? - How to perform multiple projections and lookups as aggregate in MongoDB using BsonDocument C# .NET driver? 使用mongodb C#驱动程序选择一个BsonDocument及其数组仅包含最后N个元素 - Selecting a BsonDocument with its array containing only last N elements using mongodb C# driver 如何使用官方 MongoDB C# 驱动程序将 BsonDocument 转换为强类型对象? - How to convert a BsonDocument into a strongly typed object with the official MongoDB C# driver? 如何在C#mongodb中查询BsonDocument - How to query on a BsonDocument in C# mongodb
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM