Search code examples
asp.net-mvcmongodbasp.net-corepaginationc#-3.0

Paging ASynchronously with MongoDB driver 2.9.0


I need to handle the amount of results returned when there are calls to my API (paging). I'm having real trouble achieving this with the new Async stuff that was put in the latest mongo c# drivers.

Mongo Service

    public class MongoService
    {
        private readonly IMongoCollection<BsonDocument> _bsondocs;

        public MongoService(IMongoDatabaseSettings settings)
        {
            //gets mongo connection string and database name from the
            //MongoDatabaseSettings class which gets it from appsettings.json
            var client = new MongoClient(settings.ConnectionString);
            var database = client.GetDatabase(settings.DatabaseName);

            //uses the name from MongoCollectionName variable, set by MongoDatabaseSettings.cs, again supplied from appsettings.json
            _bsondocs = database.GetCollection<BsonDocument>(settings.MongoCollectionName);

        }

        internal async Task<SearchResult> SearchAsync(string q, int page)
        {
            //this part performs the actual search
            var indexFilter = Builders<BsonDocument>.Filter.Text(q);

            var totalRecords = await _bsondocs.CountDocumentsAsync(indexFilter);
            //hard coded page size
            var pageSize = 20;

            var data = _bsondocs.Find(indexFilter)
                .Skip((page - 1) * pageSize)
                .Limit(pageSize);

            //create a new search result which can track the pages.
            var result = new SearchResult()
            {
                Data = data,
                CurrentPage = page,
                PageSize = pageSize,
                TotalRecords = totalRecords 
            };

            return result;
        }

        //this is the get method used by the controller to return full list of bson documents in a given DB collection.
        public List<BsonDocument> Get()
        {
            return _bsondocs.Find(bsonDocument => true).ToList();
        }

    }
}

SearchResult class

    public class SearchResult
    {

        public int CurrentPage { get; set; }
        public int PageSize { get; set; }
        public long TotalRecords { get; set; }
        public ICollection<BsonDocument> Data { get; set; }
    }

Call from the controller

        [HttpGet("find")]
        public async Task<IActionResult> SearchText(string q, int p)
        //public ActionResult<List<BsonDocument>> SearchText(string q) =>
        {
            SearchResult result = await _mongoService.SearchAsync(q, p);

            return Ok(result);
        }

The error I'm currently getting is:

Error CS0266 Cannot implicitly convert type 'MongoDB.Driver.IFindFluent' to 'System.Collections.Generic.ICollection'. An explicit conversion exists

But I suspect I may have wider problems, I can only find very limited documentation around the ASync methods for the latest mongo driver.


Solution

  • It turns out in this case I was just missing the .ToList() on the find function. Changing my data variable to the following solved my error and got the paging working.

                var data = _bsondocs.Find(indexFilter)
                    .Skip((page - 1) * pageSize)
                    .Limit(pageSize)
                    .ToList();