如何使用 Mongodb C# 驱动程序加入多个集合

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

我需要将 3 个集合与多个

$lookup
聚合起来 我在 C# 驱动程序中尝试过,它允许我
$lookup
用户收集,但无法执行第二个
$lookup
来设置收集。

有人可以帮忙吗?

db.Transactions.aggregate([
    {
        $lookup:
        {
            from: "Account",
            localField: "AccountId",
            foreignField: "_id",
            as: "Account"
        }
    },
       {
           $lookup:
        {
            from: "User",
            localField: "UserId",
            foreignField: "_id",
            as: "User"
        }
       }
    ])
    .match({
    })
    .project({})

这是 C# 代码:

 var account = _dbClient.GetDatabase(_dbName).GetCollection<Account>("Accounts");
var user = _dbClient.GetDatabase(_dbName).GetCollection<User>("Users");
var transaction = _dbClient.GetDatabase(_dbName).GetCollection<Transaction>("Transactions");

var result = (from t in transaction.AsQueryable()
              join a in account.AsQueryable() on t.AccountId equals a.Id
              join u in user.AsQueryable() on t.UserId equals u.Id into userList
              from acc in userList.DefaultIfEmpty()
              where acc.CompanyName.ToLower().Contains(companyName) && c.CreatedDate >= fromDate && c.CreatedDate <= toDate
              select new TransactionHistory
              {
                   Id = t.Id,
                   CompanyName = acc.CompanyName,
                   UserId = u.UserId
                   FirstName = u.FirstName
              }).ToList();

我使用 Linq 时遇到错误

$project or $group does not support {document}.

c# mongodb mongodb-csharp-2.0
2个回答
14
投票

我需要使用多个 $lookup 将 3 个集合加入聚合

给出以下课程:

public class Transactions
{
    public ObjectId Id { get; set; }
    public int UserId { get; set; }
    public int AccountId { get; set; }
    public int SettingId { get; set; }
}
public class Account
{
    public int Id {get; set;}
    public int Name {get; set;}
}
public class User
{
    public int Id {get; set;}
    public int Name {get; set;}
}
public class Setting
{
    public int Id {get; set;}
    public int Name {get; set;}
}

您可以使用 MongoDB .NET/C# 驱动程序(当前为 v2.9)执行多个 $lookup 阶段:

var collection = database.GetCollection<Transactions>("transactions");

var docs = collection.Aggregate()
                     .Lookup("account", "AccountId", "_id", "asAccounts")
                     .Lookup("user", "UserId", "_id", "asUsers")
                     .Lookup("setting", "SettingId", "_id", "asSettings")
                     .As<BsonDocument>()
                     .ToList();

foreach (var doc in docs) {
    Console.WriteLine(doc.ToJson());
}

如果您想过滤特定值,可以在之间/之前/之后添加Match。请记住,每个

Lookup
阶段后都会更改文档。

值得一提的是,如果您需要连接多个集合作为常见操作的一部分,您应该重新考虑数据库数据模型。请参阅架构设计:摘要了解更多信息。


0
投票

两者都适用于 C#.Net 8 和 Mongo Driver 2.24.0 PS:第二个不允许匿名返回类型。返回对象的类型必须显式声明。 解决方案1:

IMongoCollection<T> db = database.GetCollection<T>("user");
_companyService.db = database.GetCollection<T>("company");

var result = (from user in db.AsQueryable()
                    join company in _companyService.db.AsQueryable() on user.CompanyId equals company.Id into companyJoin
                    from company in companyJoin.DefaultIfEmpty()
                    join manager in db.AsQueryable() on user.ManagerGuid equals manager.Guid into managerJoin
                    from manager in managerJoin.DefaultIfEmpty()
                    where user.IsDisabled == false
                    select new
                    {
                       user.Id,
                       user.Name,
                       user.SurName,
                       CompanyName = company.DisplayName,
                       ManagerName = manager.Name)
                    }).ToList();

解决方案2:

   var result = db.AsQueryable<User>()
               .Where<User>( user=> user.Disabled == false)
               .Join<User, Companies, string, 
                YourCustomResponse>(_companyService.db.AsQueryable(),
                                    user => user.CompanyId,
                                    company => company.Id,                                                                                         
                                    (user, company) => new YourCustomResponse                                                                                       
                                    {
                                         Name = company.Name,
                                         // Other fields in YourCustomResponse
                                    }).ToList();
© www.soinside.com 2019 - 2024. All rights reserved.