如何使用 Linq 在 Mongo C# 2.2 驱动程序中查询嵌套列表?

Posted

技术标签:

【中文标题】如何使用 Linq 在 Mongo C# 2.2 驱动程序中查询嵌套列表?【英文标题】:How to query nested list in Mongo C# 2.2 driver with Linq? 【发布时间】:2016-06-24 05:45:52 【问题描述】:

如何使用 Linq 进行聚合查询。我知道有一个AsQueryable() 接口。但是当我进行聚合时似乎会抛出错误。

如果我有一个名为 person 的集合存储这样的数据:

  
    "Name": "Punny",
    "Interests": [
      1,
      2
    ]
  

另一个名为 interests 的集合存储数据如下:

  
    "_id":1,
    "name":"music"
  ,
  
    "_id":2,
    "name":"read"
  

我想得到这样的东西:

  
    "Name": "Punny",
    "Interests": [
      "music",
      "read"
    ]
  

我怎样才能通过 Linq 和 AsQueryable 实现这一点? 我试过这个:

_context.People.AsQueryable()
    .Select(p => new
    
      Name = p.Name,
      Interests = p.InterestingIds
       .Join(_context.Interests.AsQueryable(),
        per => per,
        i => i.Id,
        (per, i) => new i.Name)
    ).ToList();

它会抛出一个System.NotSupportedException

System.NotSupportedException : 表达式树 documentInterestingIds.Join([FunnyMongoBlog.interest], per => per, i => i.Id, ( per, i) => new f__AnonymousType1`1(Name = i.Name)).

我尝试了两次数据库之旅:

      var person = _context.People.AsQueryable()
    .Single(p => p.Name == "Punny");
  var ids = person.InterestingIds;
  var query = _context.Interests.AsQueryable()
    .Where(i => ids.Contains(i.Id)).ToList();
  var result = new
  
    person.Name,
    Interest = query
  ;

这是可行的,但我想知道我们是否可以一次性完成,以便数据库可以处理聚合。

【问题讨论】:

【参考方案1】:

您可以在聚合框架中执行此操作,但我建议在 mongoDB 中使用 subDocumnets 的功能并将这些元素完全嵌入到主文档中。换句话说,我们需要从关系思维转向文档思维。

我建议的对象形状:


    "Name" : "Punny",
    "Interests" : [
            "_id" : 1,
            "name" : "music"
        , 
            "_id" : 2,
            "name" : "read"
        
    ]

在 C# 代码中

class MyClass 
    public string Name;
    public List < Interest > Interests;


class Interest 
    public int Id;
    public string Name;

现在请找到所请求的转换所需的 bson 文档:

db.col.aggregate([
            $unwind : "$Interests"
        , 
            $lookup : 
                from : "interests",
                localField : "Interests",
                foreignField : "_id",
                as : "interest"
            
        , 
            // now we need to reshape document
            $project : 
                _id : 1,
                Name : 1,
                Interests : "$interest.name"
            
        ,
        //group documents back
        
            $group : 
                _id : 
                    id : "$_id",
                    name : "$Name"
                ,
                Interests : 
                    $push : "$Interests"
                
            
        , 
            //final reshape
            _id : "$_id.id",
            Name : "$_id.name",
            Interests : 1
        
    ])

并决定嵌入是否值得一试:-)

欢迎任何cmets!

【讨论】:

感谢您的回复,但我正在考虑使用新的 Linq 语法进行查询。而不是使用预定义的 BsonDocument。据我所知,有一个AsQueryable() 接口,然后我可以将Linq 转换为查询。 继续吧 - 我刚刚包含这个查询是为了向您展示您的文档设计的巨大弱点......

以上是关于如何使用 Linq 在 Mongo C# 2.2 驱动程序中查询嵌套列表?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中使用 LINQ 应用右外连接?

如何在 C# 中使用 LINQ 过滤嵌套字典?

如何使用 LINQ 在 C# 中实现梯度下降算法?

如何使用基于 SQL Query 的连接在 C# 中编写 LINQ?

使用 C# 中的 NEST 库调用 elasticsearch 时,如何向 linq 语句添加条件逻辑?

如何在 C# WinForms 中使用 LINQ 从 DataGridView 中选择多个字段