在带有 .NET 驱动程序的 Azure DocumentDB 中使用 MongoDB 会引发 MongoCommandException
Using MongoDB in Azure DocumentDB with .NET driver throws MongoCommandException
我正在使用 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&queryTerm=TitaniC 调用控制器时,MongoDB 命令输出为:
{find({ "$or" : [{ "imdb_code" : /^TitaniC$/i }, { "title" : /^TitaniC$/i }, { "cast.name" : /^TitaniC$/i }, { "cast.imdb_code" : /^TitaniC$/i }] }).sort({ "date_uploaded_unix" : -1 }).skip(0).limit(20) )}
这看起来不错并检索了适当的文档。
但非常随机地,我从 Azure 收到 429 HTTP 错误告诉我:
'命令查找失败:消息:{"Errors":["Request rate is large"]}
但是,我调用了我的 API 一次,没有其他请求...
为什么会发生这种情况;- 当 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();
我正在使用 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&queryTerm=TitaniC 调用控制器时,MongoDB 命令输出为:
{find({ "$or" : [{ "imdb_code" : /^TitaniC$/i }, { "title" : /^TitaniC$/i }, { "cast.name" : /^TitaniC$/i }, { "cast.imdb_code" : /^TitaniC$/i }] }).sort({ "date_uploaded_unix" : -1 }).skip(0).limit(20) )}
这看起来不错并检索了适当的文档。
但非常随机地,我从 Azure 收到 429 HTTP 错误告诉我:
'命令查找失败:消息:{"Errors":["Request rate is large"]}
但是,我调用了我的 API 一次,没有其他请求...
为什么会发生这种情况;- 当 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();