在Azure DocumentDB中使用带有.NET驱动程序的MongoDB会抛出MongoCommandException

时间:2017-03-01 16:16:22

标签: c# mongodb azure asp.net-core azure-cosmosdb

我正在使用Azure DocumentDB来操作MongoDB集合。

根据我的Azure标准计划,我有1000 RU / s的限制。

当我尝试从MongoDB集合中过滤和排序一些数据时,会遇到我遇到的问题。

这是我使用.NET MongoDB驱动程序2.4.2.0的C#代码:

    // GET api/movies
    [HttpGet]
    public async Task<IActionResult> Get([RequiredFromQuery] int page, [FromQuery] int limit,
        [FromQuery] string quality, [FromQuery] int minimumRating, [FromQuery] string queryTerm, [FromQuery] string genre, [FromQuery] string sortBy, [FromQuery] string orderBy)
    {
        var nbMoviesPerPage = 20;
        if (limit >= 20 && limit <= 50)
        {
            nbMoviesPerPage = limit;
        }

        var currentPage = 1;
        if (page >= 1)
        {
            currentPage = page;
        }

        var movies = _mongoDbService.GetCollection(Constants.MoviesCollectionName);
        var filter = Builders<MovieBson>.Filter.Empty;
        var sort = Builders<MovieBson>.Sort.Descending(movie => movie.DateUploadedUnix);

        if (!string.IsNullOrWhiteSpace(quality) &&
            (quality == "720p" || quality == "1080p" || quality.ToLower() == "3d"))
        {
            filter = filter & Builders<MovieBson>.Filter.Eq("torrents.quality", quality);
        }

        if (minimumRating > 0 && minimumRating < 10)
        {
            filter = filter & Builders<MovieBson>.Filter.Gt("rating", minimumRating);
        }

        if (!string.IsNullOrWhiteSpace(queryTerm))
        {
            filter = filter &
                     (Builders<MovieBson>.Filter.Regex("imdb_code", new BsonRegularExpression("/^" + queryTerm + "$/i")) |
                      Builders<MovieBson>.Filter.Regex("title", new BsonRegularExpression("/^" + queryTerm + "$/i")) |
                      Builders<MovieBson>.Filter.Regex("cast.name", new BsonRegularExpression("/^" + queryTerm + "$/i")) |
                      Builders<MovieBson>.Filter.Regex("cast.imdb_code", new BsonRegularExpression("/^" + queryTerm + "$/i")));
        }

        if (!string.IsNullOrWhiteSpace(genre))
        {
            filter = filter & Builders<MovieBson>.Filter.In("genres", new List<string>
            {
                genre
            });
        }

        if (!string.IsNullOrWhiteSpace(sortBy))
        {
            switch (sortBy)
            {
                case "title":
                    sort = Builders<MovieBson>.Sort.Ascending(movie => movie.Title);
                    break;
                case "year":
                    sort = Builders<MovieBson>.Sort.Descending(movie => movie.Year);
                    break;
                case "rating":
                    sort = Builders<MovieBson>.Sort.Descending(movie => movie.Rating);
                    break;
                case "peers":
                    sort =
                        Builders<MovieBson>.Sort.Descending(movie => movie.Torrents.Select(torrent => torrent.Peers));
                    break;
                case "seeds":
                    sort =
                        Builders<MovieBson>.Sort.Descending(movie => movie.Torrents.Select(torrent => torrent.Seeds));
                    break;
                case "download_count":
                    sort = Builders<MovieBson>.Sort.Descending(movie => movie.DownloadCount);
                    break;
                case "like_count":
                    sort = Builders<MovieBson>.Sort.Descending(movie => movie.LikeCount);
                    break;
                case "date_added":
                    sort = Builders<MovieBson>.Sort.Descending(movie => movie.DateUploadedUnix);
                    break;
                default:
                    sort = Builders<MovieBson>.Sort.Descending(movie => movie.DateUploadedUnix);
                    break;
            }
        }

        var filteredMovies = movies.Find(filter);
        var totalTask = filteredMovies.CountAsync();
        var moviesTask = filteredMovies.Skip((currentPage - 1) * nbMoviesPerPage).Limit(nbMoviesPerPage).Sort(sort).ToListAsync();
        await Task.WhenAll(totalTask, moviesTask);

        if (!string.IsNullOrWhiteSpace(orderBy))
        {
            switch (orderBy)
            {
                case "desc":
                    moviesTask.Result.Reverse();
                    break;
            }
        }

        return
            Json(new MovieResponse
            {
                TotalMovies = totalTask.Result,
                Movies = JsonConvert.DeserializeObject<IEnumerable<MovieJson>>(moviesTask.Result.ToJson())
            });
    }

当我使用路径 api / movies?page = 1&amp; queryTerm = TitaniC 呼叫我的控制器时,MongoDB命令输出为:

{find({&#34; $或&#34;:[{&#34; imdb_code&#34;:/ ^ TitaniC $ / i},{&#34; title&#34;:/ ^ TitaniC $ / i},{&#34; cast.name&#34;:/ ^ TitaniC $ / i},{&#34; cast.imdb_code&#34;:/ ^ TitaniC $ / i}]})。sort({ &#34; date_uploaded_unix&#34;: - 1})。skip(0).limit(20)}

看起来很好,并检索相应的文件。

但非常随机,我从Azure收到429 HTTP错误告诉我:

&#39;命令查找失败:消息:{&#34;错误&#34;:[&#34;请求率很高&#34;]}

但是,我只调用了一次API,没有其他请求......

1 个答案:

答案 0 :(得分:1)

为什么会发生这种情况; - 当MongoDB无法使用索引获取查询的排序顺序时,它会将结果排序到内存中。如果排序操作消耗超过32兆字节,则抛出上述错误。解决此问题的一种可能方法是使用allowDiskUse选项启用聚合管道阶段以将数据写入临时文件。结帐My blog for details

var data = await movies.Aggregate(new AggregateOptions
        {
            AllowDiskUse = true,
        })
            .Match({})//Insert your query here
            .Skip(2)
            .Sort({ "_id", -1 } )//Insert your sort options here
            .Limit(20)
            .ToListAsync();