【问题标题】:Mongo gives me "sort exceeded memory limit" exception even when using pagination即使使用分页,Mongo 也会给我“排序超出内存限制”异常
【发布时间】:2021-09-23 18:39:42
【问题描述】:

我正在尝试使用 MongoDB 为我的项目创建分页搜索。即使使用 Limit 和 Skip,它也会引发“Sort Exceeded Memory Limit”异常。这有点奇怪,因为我将查询限制为仅 10 个。

 public async Task<(List<Contato>, long)> BuscarPorFiltro(FiltroContatoDTO filtro, int page, int pageSize)
    {
        var collection = _mongoDBContext.MongoDBConexao.GetCollection<Contato>(_collection);

        var idsFluxoCompleto = await fluxoCompletoRepository.BuscarFluxoCompletoPorEmpresaId(Guid.Parse(filtro.EmpresaId));

        var sortBuilder = Builders<Contato>.Sort;
        var sort = sortBuilder.Descending(c => c.DataHora);

        var options = new FindOptions<Contato>();
        options.Skip = page * pageSize;
        options.Limit = pageSize;
        options.Sort = sort;

        var filterBuilder = Builders<Contato>.Filter;
        var filter = idsFluxoCompleto != null && idsFluxoCompleto.Count > 0 ? filterBuilder.Where(c => idsFluxoCompleto.Contains(c.IdFluxoCompleto)) : filterBuilder.Empty;

        //Filtros Opcionais
        if (filtro.DataInicio.HasValue)
            filter = filter & filterBuilder.Gte(x => x.DataHora, filtro.DataInicio.Value);
        
        if (filtro.DataFim.HasValue)
            filter = filter & filterBuilder.Lt(x => x.DataHora, filtro.DataFim.Value);

        if (filtro.FluxoId.HasValue)
            filter = filter & filterBuilder.Eq(x => x.IdFluxoCompleto, filtro.FluxoId.Value);

        if (!String.IsNullOrWhiteSpace(filtro.Telefone))
            filter = filter & filterBuilder.Where(x => x.Telefone.Contains(filtro.Telefone));

        if (filtro.CompletouFluxo.HasValue)
            filter = filter & filterBuilder.Eq(x => x.Status, filtro.CompletouFluxo.Value);

        if (filtro.CancelouFluxo.HasValue)
            filter = filter & filterBuilder.Eq(x => x.CancelouFluxo, filtro.CancelouFluxo.Value);

        if (filtro.IntegrouCRM.HasValue)
            filter = filter & filterBuilder.Eq(x => x.RealizouIntegracaoCRM, filtro.IntegrouCRM.Value);

        if (filtro.Ultrapassou24Horas.HasValue)
            filter = filter & filterBuilder.Eq(x => x.Ultrapassou24Horas, filtro.Ultrapassou24Horas.Value);

        if (!String.IsNullOrWhiteSpace(filtro.Temperatura))
            filter = filter & filterBuilder.Eq(x => x.Lead, filtro.Temperatura.ToUpper());

        if (filtro.Origem.HasValue)
            filter = filter & filterBuilder.Eq(x => x.Origem, filtro.Origem.Value);

        if (filtro.Unidade.HasValue)
            filter = filter & filterBuilder.Eq(x => x.Unidade, filtro.Unidade.Value);

        var count = await collection.CountDocumentsAsync(filter);
        var result = await collection.FindAsync(filter, options);

        return (result.ToList(), count);
    }

我知道 AllowDiskUse 选项,但我不想使用它,因为这个特定的查询应该只返回 10 个项目并且它不应该超过 100Mb 的限制退回的文件。

【问题讨论】:

    标签: c# .net mongodb mongodb-query mongodb-.net-driver


    【解决方案1】:

    虽然您将结果限制为 10 个文档,但 DB 必须过滤所有匹配文档并根据您的排序条件进行排序,如果整个匹配的数据集不适合内存限制 DB 会抛出错误。

    假设您有 10,000 个文档并且您编写过滤器将匹配的文档减少到 5000 个,然后您有一些排序/跳过标准,然后 DB 必须对匹配的 5000 个文档上的文档进行排序和跳过,如果 5000 个文档不适合在内存中它会抛出错误。

    将允许磁盘使用标志设置为 true 并没有什么害处,只有在匹配的数据集大小不符合限制时才会使用它。

    文档:https://docs.mongodb.com/manual/reference/command/aggregate/#command-fields

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-05
      • 1970-01-01
      • 2018-10-27
      • 1970-01-01
      • 2022-10-30
      • 2018-02-10
      • 1970-01-01
      • 2020-07-20
      相关资源
      最近更新 更多