使用 $facet 阶段的 MongoDB C# 驱动程序中的投影问题

Issue with Projection in MongoDB C# Driver Using $facet Stage

提问人:J.Paravicini 提问时间:11/16/2023 更新时间:11/16/2023 访问量:15

问:

背景:

我正在使用 MongoDB C# 驱动程序,在聚合管道中使用舞台时遇到投影问题。投影在简单方案中按预期工作,但未能在阶段中应用相同的逻辑。$facet$facet

问题:

我的订单集合中有一个字段。我想在它为 null 时将其设置为回退值。投影在基本方案中正常工作,但在对舞台使用更复杂的查询时失败。CustomerMail$facet

首先,这就是我调用以下方法的方式:

await Repository.Query(_ => true, new List<SortExpression<Order>>(), x => new AdminOrderModel
                {
                    CustomerMail = x.CustomerMail ?? "fallback",
                    OrderDate = x.OrderDate,
                    State = x.State.ToString(),
                    Id = x.Id,
                    OrderName = x.OrderName,
                },
                1, 10, CancellationToken.None)
            .ConfigureAwait(false);

工作场景:

下面是工作方案的代码:

public async Task<PagedList<T>> Query<T>(
    Expression<Func<Order, bool>> filterExpression,
    IList<SortExpression<Order>> sortExpressions,
    Expression<Func<Order, T>> projectionExpression,
    int pageNumber,
    int pageSize,
    CancellationToken cancellationToken)
{
    var filter = Builders<Order>.Filter.Where(filterExpression);
    var sort = sortExpressions.IsNullOrEmpty() ? null : Builders<Order>.Sort.Combine(sortExpressions.Select(x => x.ToSortDefinition()));
    var projection = Builders<Order>.Projection.Expression(projectionExpression);
    var projectionDefinition = PipelineStageDefinitionBuilder.Project(projection);

    var x = await _collection
        .Aggregate()
        .Match(filter)
        .AppendStage(projectionDefinition)
        .ToListAsync(cancellationToken)
        .ConfigureAwait(false);

    // Additional implementation...
}

此处,当它为 null 时,正确设置为“fallback”。CustomerMail

具有$facet的非工作场景:

但是,当我在方法的$facet阶段内使用类似的投影时,不会应用回退。AggregateByPageAsyncCustomerMail

public async Task<PagedList<T>> Query<T>(
        Expression<Func<Order, bool>> filterExpression,
        IList<SortExpression<Order>> sortExpressions,
        Expression<Func<Order, T>> projectionExpression,
        int pageNumber,
        int pageSize,
        CancellationToken cancellationToken)
    {
        var filter = Builders<Order>.Filter.Where(filterExpression);
        var sort = sortExpressions.IsNullOrEmpty()
            ? null
            : Builders<Order>.Sort.Combine(sortExpressions.Select(x => x.ToSortDefinition()));
        var projection = Builders<Order>.Projection.Expression(projectionExpression);
        var projectionDefinition = PipelineStageDefinitionBuilder.Project(projection);

        var countFacet = AggregateFacet.Create("count",
            PipelineDefinition<Order, AggregateCountResult>.Create(new[]
            {
                PipelineStageDefinitionBuilder.Count<Order>(),
            }));

        var dataFacetPipelineStages = new List<IPipelineStageDefinition>
        {
            PipelineStageDefinitionBuilder.Skip<Order>((pageNumber - 1) * pageSize),
            PipelineStageDefinitionBuilder.Limit<Order>(pageSize),
            PipelineStageDefinitionBuilder.Project(projection),
        };
        if (sort != null)
        {
            dataFacetPipelineStages.Insert(0, PipelineStageDefinitionBuilder.Sort(sort));
        }

        var dataFacet = AggregateFacet.Create("data",
            PipelineDefinition<Order, AdminOrderModel>.Create(dataFacetPipelineStages));

        var aggregation = await _collection.Aggregate()
            .Match(filter)
            .Facet(countFacet, dataFacet)
            .ToListAsync(cancellationToken: cancellationToken)
            .ConfigureAwait(false);
    }

在此方案中,当 CustomerMail 在阶段中为 null 时,它不会设置为“回退”。$facet

我试图在mongodb中分析查询,奇怪的是,两个查询中的投影部分完全相同:

        '$project': {
          _id: 1,
          customerMail: 1,
          orderDate: 1,
          orderName: 1,
          state: 1
        }

问题

为什么在$facet阶段中使用投影时不应用 CustomerMail 的回退值?是否有其他方法可以处理 $facet 内投影中的空值?

C# MongoDB 查询 聚合框架 投影

评论


答: 暂无答案