Mongo 即使在使用分页时也给我 "sort exceeded memory limit" 异常

Mongo gives me "sort exceeded memory limit" exception even when using pagination

我正在尝试使用 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 选项,但我不想使用它,因为这个特定查询应该 return只有 10 个项目,并且不应超过 returned 文档的 100Mb 限制。

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

考虑这样一种情况,您有 10,000 个文档,您编写了将匹配文档减少到 5000 个的过滤器,然后您有一些 sort/skip 条件,然后数据库必须对匹配的 5000 个文档进行排序和跳过文档,如果这 5000 个文档不适合内存,它会抛出错误。

将 Allow disk use flag 设置为 true 没有坏处,只有当匹配的数据集大小不符合限制时才会使用它。

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