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

5
如何使用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: 表达式树中不支持类型为 System.Linq.Enumerable 的 Join。{document}{InterestingIds}.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个回答

0

你可以使用聚合框架来完成,但我建议在MongoDB中使用子文档的强大功能,并将这些元素完全嵌入到主文档中。换句话说,我们需要从关系型思维转向文档思维。

我建议的对象形状:

{
    "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
        }
    ])

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

欢迎任何评论!


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接