linq 如何使用MongoDB C#驱动程序投影查询嵌套列表

pkbketx9  于 2022-12-06  发布在  Go
关注(0)|答案(1)|浏览(134)

假设我的MongoDB中有以下数据:

{
  "_id": {
    "$oid": "62baf9a2851424fdb8c226f8"
  },
  "Name": "Team A",
  "TeamData": {
    "Players": [
      {
        "FirstName": "First Name A",
        "LastName": "Last Name A"
      },
      {
        "FirstName": "First Name B",
        "LastName": "Last Name B"
      }
    ]
  }
}

我只想查询LastNameFirstName应该是null
使用点标记法时,查询投影如下所示:

{
    "TeamData.Players.LastName": 1
}

我如何使用C#驱动程序的LINQ支持来实现这一点?我能够接近下面的代码,但还不完全是。

public IEnumerable<TeamDto> GetTeam()
{
    return _collection.Find(filter).Project(x => new TeamDto
    {
        Id = x.Id,
        TeamData = new TeamDataDto
        {
            Players = x.TeamData.Select(y => new PlayerDto
            {
                LastName = y.LastName
            })
        }
    });
}

其结果是:玩家数组是填充的,但是有null值。我也尝试了我的手在.Project()内的IncludeExclude,也是无效的。有人能给我一个提示吗?

编辑:我的问题实际上非常类似于this one,但使用的是LINQ。我知道有一种方法可以在.Project中使用点标记,但这也不是我想要的。谢谢。

1l5u6lss

1l5u6lss1#

在我看来,这看起来像是一个bug(或者至少是一个有点意外的行为)。你的预测实际上是有效的。我把它简化成了下面的形式:

var result = coll.Find("{}")
   .Project(x => x.TeamData.Players.Select(c => c.LastName))
   .ToList();

本例实际生成的请求为:

{
    "find": "coll",
    "filter": {},
    "projection": {
        "Players.LastName": 1,
        "TeamData.Players": 1,
        "_id": 0
    }
}

这个水平投影包含"TeamData.Players": 1,这有点出乎意料,即使我们没有配置它,它也会导致使用FirstName创建结果:

{
    "TeamData": {
        "Players": [{
                "FirstName": "First Name A",
                "LastName": "Last Name A"
            }, {
                "FirstName": "First Name B",
                "LastName": "Last Name B"
            }
        ]
    }
}

您也可以通过以下方式在shell中检查它:

db.runCommand({ "find" : "coll", "filter" : { }, "projection" : { "Players.LastName" : 1, "TeamData.Players" : 1, "_id" : 0 } })

上述投影的问题很小,可以通过直接指定预期投影来修复:

var result = coll.Find("{}")
   .Project("{ 'TeamData.Players.LastName': 1 }")
   .ToList();

只生成简单的预期MQL:

{ "find" : "coll", "filter" : { }, "projection" : { "TeamData.Players.LastName" : 1 } }

依次返回预期文档:

{
    "_id": ObjectId("62d94cdeed9104ede4a35d75"),
    "TeamData": {
        "Players": [{
                "LastName": "Last Name A"
            }, {
                "LastName": "Last Name B"
            }
        ]
    }
}

但问题是当服务器返回文档时,驱动程序还应该将此文档反序列化为投影输出。(TeamDataPlayers),因此驱动程序无法执行此操作。由于他无法将TeamData文档转换为字符串,只返回null,通过替换BsonDocument上的一个集合泛型类型可以看到实际返回的文档:

var coll = db.GetCollection<BsonDocument>("coll");
  var result = coll.Find("{}")
       .Project("{ 'TeamData.Players.LastName': 1 }")
       .ToList();

因此,问题是驱动程序端服务器响应的反序列化不正确,这就是为什么结果项为null的原因。

相关问题