【问题标题】:Overflow sort stage buffered data usage when trying to skip and take from MongoDB repository尝试从 MongoDB 存储库跳过和获取时溢出排序阶段缓冲数据使用
【发布时间】:2015-08-03 17:38:47
【问题描述】:

我有一个经典的支持 REST 和 ODATA 的 Web API 控制器调用基于 MongoDB 的存储库模式实现。

我一直在努力

溢出排序阶段缓冲数据使用量 33556193 字节超出内部限制 33554432 字节异常

当我尝试跳过前 12010 多条记录并获得前 10 名时

?$skip=12020&$top=10&$orderby=Serial

经过一番搜索,我尝试在 Serial 上实现索引,例如

private void GetCollection() //is like DBSet of some entity
{
  _collection = _dbContext.Database
     .GetCollection<TEntity>(typeof(TEntity).Name);
  Type typeParameterType = typeof(TEntity);
  if (typeParameterType.Name == "StoreCommand")
    if (_collection.IndexExists("Serial") == false)
      _collection.CreateIndex(IndexKeys<StoreCommand>.Ascending(_ => _.Serial));
}

我的存储库实现是这样的。

    public class MongoDbRepository<TEntity> :
    IRepository<TEntity> where
        TEntity : EntityBase
{
    private MongoCollection<TEntity> _collection;

    private SNDbContext _dbContext;
    public MongoDbRepository(SNDbContext dbContext)
    {
        _dbContext = dbContext;
        GetCollection();
    }
    private void GetCollection()
    {
        _collection = _dbContext.Database
            .GetCollection<TEntity>(typeof(TEntity).Name);
    }
    public IQueryable<TEntity> GetAll()
    {
        return _collection.AsQueryable(); 
    }//............And other functions after this

}

来自服务层的调用是这样的

 IQueryable<StoreCommand> GetAllStoreCommands() 
  {
     return _uow.StoreCommands.GetAll(); 
   } 

其中 SNDbContext 包含与使用 MongoClient 和连接字符串获取数据库相关的所有代码。

【问题讨论】:

    标签: c# mongodb asp.net-web-api mongodb-.net-driver asp.net-web-api-odata


    【解决方案1】:

    问题在于,在您的存储库实现(未显示)中,您从 MongoDB 获取所有数据,然后所有这些数据都在缓冲中排序并在内存中排序以允许跳过和获取。

    您需要做的是通过以下两种方式中的任何一种来修改您的存储库:

    • 返回一个纯可查询对象,这样您就可以组合查询的其余部分并仍然在 MongoDB 引擎上执行它
    • 直接公开一个接收参数以跳过和采用的方法,并在数据库中直接执行查询。

    你可以用光标来实现它,像这样:

    var collection = db.GetCollection<YourType>("yourtype");
    var sort = SortBy<YourType>
                .Ascending(p => p.YourProperty1)
                .Descending(p => p.YourProperty2);
    MongoCursor<YourType> cursor = collection
      .FindAll()
      .SetSortOrder(sort)
      .SetSkip(12010)
      .SetLimit(10);
    

    如果你迭代这个游标,你应该不会遇到任何问题。

    您还可以定义和执行SelectQuery,指定SkipTake 值。查看文档:SelectQuery Properties

    【讨论】:

    • 所以我更新了我的问题。我希望使用您建议的选项一。我已经返回纯 IQueryable。由我的服务层返回 public IQueryable GetAllStoreCommands() { return _uow.StoreCommands.GetAll(); } 你能告诉我组成查询的其余部分是什么意思吗?
    猜你喜欢
    • 2015-02-02
    • 2016-01-15
    • 2017-03-23
    • 2015-01-17
    • 1970-01-01
    • 1970-01-01
    • 2014-10-22
    相关资源
    最近更新 更多