如何使用 C# 类聚合 MongoDB 集合

问题描述 投票:0回答:1

这是一个高度简化的示例,其中我在 MongoDB 中的不同集合中拥有三个类集合(

Team
League
Player
)。我在 .NET 8 Blazor 服务器应用程序中使用 C# MongoDB 驱动程序。

每个对象的数据都可以独立更新,并且这些对象可以在其他类的多个实例中使用。因此,我试图避免将所有数据存储在团队的单个文档集合中。

我目前正在使用下面的

Team
类 (
TeamData
) 将
IMongoCollection<TeamData>
存储在数据库中。但是,当我从数据库中检索
TeamData
时,我希望它是完全实现的
Team
类。

当我使用aggregateasync从数据库获取这些数据时,我不知道如何让这些数据“加入”。我正在寻求有关如何使用 MongoDB C# 驱动程序从数据库中获取这些作为完全实现的类的帮助。我见过的所有示例都需要大量“魔术字符串”数据,而不是使用代码中已有的类和类数据。

我觉得 GetAllTeams 方法底部的那行是我被卡住的地方。

public class Player
{
    [BsonId, BsonRepresentation(BsonType.ObjectId)]
    public string Id { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public int Handicap { get; set; }
}

public class League
{
    [BsonId, BsonRepresentation(BsonType.ObjectId)]
    public string Id { get; set; }

    public string Name { get; set }
}

public class Team
{
    [BsonId, BsonRepresentation(BsonType.ObjectId)]
    public string Id { get; set; }

    public int Number { get; set; }

    public League League { get; set; }

    public Player Player1 { get; set; }

    public Player Player2 { get; set; }
}

// this is how I am currently storing the data for the team in the database, where I have references to the other objects.
public Class TeamData
{
    [BsonId, BsonRepresentation(BsonType.ObjectId)]
    public string Id { get; set; }

    public int Number { get; set; }

    [BsonRepresentation(BsonType.ObjectId)]
    public string LeagueId { get; set; }

    [BsonRepresentation(BsonType.ObjectId)]
    public string Player1Id { get; set; }

    [BsonRepresentation(BsonType.ObjectId)]
    public string Player2Id { get; set; }
}

public async Task<List<Team>> GetAllTeams()
{
    IMongoCollection<TeamData> teamCollection = Database.GetCollection<TeamData>("Teams");
    IMongoCollection<League> leagueCollection = Database.GetCollection<League>("Leagues");
    IMongoCollection<Player> playerCollection = Database.GetCollection<Player>("Players");

    var result = teamCollection.FindAsync(_ => true).AggregateAsync(what needs to go here to make this work);

    return result.ToList();
}

就上下文而言,这就是我今天所做的,但这感觉非常冗长且低效。

public override async Task<List<Team>> GetAllAsync()
{
    IMongoCollection<TeamData> teamCollection = Database.GetCollection<TeamData>("Teams"_
    IMongoCollection<League> leagues = Database.GetCollection<League>("Leagues");
    IMongoCollection<Player> players = Database.GetCollection<Player>("Players");

    var data = await teamCollection.FindAsync(_ => true);

    List<Team> teams = [];

    foreach (TeamData t in data.ToList())
    {
        teams.Add(new Team()
        {
            Id = t.Id,
            Number = t.Number,
            League = (await leagues.FindAsync(l => l.Id == t.LeagueId)).First(),
            Player1 = (await players.FindAsync(p => p.Id == t.Player1Id)).First(),
            Player2 = (await players.FindAsync(p => p.Id == t.Player2Id)).First(),
        });
    }

    return teams;
}
c# mongodb aggregation-framework
1个回答
0
投票

您可以通过 LINQ 查询表达式对多个集合执行查找联接,我认为这是最简单的方法。

方法一:LINQ查询表达式

var data = (from team in teamCollection.AsQueryable()
            join league in leagues.AsQueryable() on team.LeagueId equals league.Id
            join player1 in players.AsQueryable() on team.Player1Id equals player1.Id
            join player2 in players.AsQueryable() on team.Player2Id equals player2.Id
            select new Team
            {
                Id = team.Id,
                League = league,
                Number = team.Number,
                Player1 = player1,
                Player2 = player2,
            }).ToList();

或者,您可以编写聚合查询:

db.getCollection('Teams').aggregate(
  [
    {
      $lookup: {
        from: 'Leagues',
        localField: 'LeagueId',
        foreignField: '_id',
        as: 'Leagues'
      }
    },
    {
      $lookup: {
        from: 'Players',
        localField: 'Player1Id',
        foreignField: '_id',
        as: 'PlayerOnes'
      }
    },
    {
      $lookup: {
        from: 'Players',
        localField: 'Player2Id',
        foreignField: '_id',
        as: 'PlayerTwos'
      }
    },
    {
      $project: {
        _id: 1,
        Number: 1,
        League: { $first: '$Leagues' },
        Player1: { $first: '$PlayerOnes' },
        Player2: { $first: '$PlayerTwos' }
      }
    }
  ]
);

方法 2:使用

BsonDocument

进行聚合管道
var data = await teamCollection.Aggregate<Team>(new BsonDocument[]
    {
        new BsonDocument("$lookup",
            new BsonDocument
                {
                    { "from", "Leagues" },
                    { "localField", "LeagueId" },
                    { "foreignField", "_id" },
                    { "as", "Leagues" }
                }),
        new BsonDocument("$lookup",
            new BsonDocument
                {
                    { "from", "Players" },
                    { "localField", "Player1Id" },
                    { "foreignField", "_id" },
                    { "as", "PlayerOnes" }
                }),
        new BsonDocument("$lookup",
            new BsonDocument
                {
                    { "from", "Players" },
                    { "localField", "Player2Id" },
                    { "foreignField", "_id" },
                    { "as", "PlayerTwos" }
                }),
        new BsonDocument("$project",
            new BsonDocument
            {
                { "_id", 1 },
                { "Number", 1 },
                { "League",
                    new BsonDocument("$first", "$Leagues") },
                { "Player1",
                    new BsonDocument("$first", "$PlayerOnes") },
                { "Player2",
                    new BsonDocument("$first", "$PlayerTwos") }
            })
    }).ToListAsync();
© www.soinside.com 2019 - 2024. All rights reserved.