.NET MongoDB 错误的投影规范

.NET MongoDB Bad Projection Specification

我正在将系统从旧 Mongo 驱动程序升级到新驱动程序。我遇到了以下查询的问题。

        var orgsUnitReadModels = _readModelService.Queryable<OrganisationalUnitReadModel>()
            .Where(x => locations.Contains(x.Id))
            .Select(x => new AuditLocationItemViewModel
            {
                Id = x.Id,
                Name = x.Name,
                AuditRecordId = auditRecordId,
                Type = type,
                IsArchived = !x.IsVisible,
                AuditStatus = auditStatus
            }).ToList();

它产生以下错误消息,我不明白。如果您能协助解释这意味着什么以及如何解决它,我将不胜感激。

MongoDB.Driver.MongoCommandException: 'Command aggregate failed: Bad projection specification, cannot exclude fields other than '_id' in an inclusion projection: { Id: "$_id", Name: "$Name", AuditRecordId: BinData(3, 5797FCCCA90C8644B4CB84FED4236D4B), Type: 0, IsArchived: { $not: [ "$IsVisible" ] }, AuditStatus: 2, _id: 0 }.'

在此示例中,LINQ 的 Select 语句被翻译成 MongoDB 的 $project。通常,您使用 0(或 false)排除字段,并使用 1true 将字段包含在最终结果集中。当然,您也可以使用美元语法来引用现有字段,例如 Name.

问题是您还试图将一些 in-memory 常量值作为投影的一部分。不幸的是,其中一个 (type) 等于 0,这被解释为好像您想从管道结果中排除一个名为 Type 的字段。

由于这种歧义 MongoDB 引入了 $literal 运算符,您可以在 Mongo shell:

中尝试以下语法
db.col.aggregate([{ $project: { _id: 0, Id: 1, Name: 1, Type: { $literal: 0 } } }])

它将return 0 作为您期望的常量值。 MongoDB .NET 驱动程序文档提到了文字 here 但它看起来只适用于字符串。

有几种方法可以解决您的问题,我认为更简单的方法是先 运行 更简单的 .Select 语句,然后使用 .ToList() 确保查询已实现.完成后,您可以 运行 另一个 in-memory .Select() 来构建您的 OrganisationalUnitReadModel:

.Where(x => locations.Contains(x.Id))
.Select(x => new { x.Id, x.Name, x.IsVisible }).ToList()
.Select(x => new AuditLocationItemViewModel
{
    Id = x.Id,
    Name = x.Name,
    Type = type,
    IsArchived = !x.IsVisible,
    AuditStatus = auditStatus
}).ToList();