【问题标题】:Sub-Query or Join with embedded/nested document using C# LINQ with MongoDB使用 C# LINQ 和 MongoDB 对嵌入式/嵌套文档进行子查询或联接
【发布时间】:2020-03-09 04:29:52
【问题描述】:

我正在尝试做类似下面示例的操作,但遇到异常 - System.ArgumentException:方法的“System.Collections.Generic.IEnumerable1 ' cannot be used for parameter of type 'System.Linq.IQueryable1”类型的表达式。 这是我的代码和相关类。我该如何解决这个问题,除了尝试做之外还有什么办法。

    var channels = _channelService.Collection;
    var tracks = _trackService.Collection;

    var query = from b in tracks.AsQueryable()
                select b;

    var data = (from q in channels.AsQueryable()
               from p in q.Episodes
               //from x in  trackcoll.AsQueryable()
               select new
               {
                   p,
                   Tracks = query.Where(w => p.Tracks.Contains(w.Id))
               }).ToList();

// Related classes
    public class ContentBase : IAuditable
    {
        public string Id { get; set ; }
        public string CreatedBy { get ; set ; }
        public string CreatedOn { get ; set ; }
        public string UpdatedBy { get ; set ; }
        public string UpdatedOn { get; set; }
    }

    public class Channel: ContentBase
    {
        public List<Episode> Episodes { get; set; }
    }

    public class Episode: ContentBase
    {
        // List of track Id
        public List<string> Tracks { get; set; }
    }
    public class Track: ContentBase
    {
        public string TrackUrl { get; set; }
        public string Duration { get; set; }
        public string Size { get; set; }
        public string ContentType { get; set;

    }

【问题讨论】:

  • 您可以将您的 c# 类(频道、曲目、剧集)添加到问题中吗?
  • @ĐĵΝιΓΞΗΛψΚ请检查

标签: c# mongodb linq mongodb-.net-driver


【解决方案1】:

MongoDB 对连接的 LINQ 支持仅限于相等连接,如 here 所述。您的表达式无法转换为聚合框架的 $lookup,因为 .Contains() 没有等效语法。

因此,您必须运行更接近聚合框架语法的操作。一个例子是一个流畅的聚合接口,它允许你运行与聚合框架的操作符同名的扩展方法。试试:

var q = _channels.Aggregate()
                    .Unwind(x => x.Episodes)
                    .Lookup(
                        foreignCollectionName:"tracks", 
                        localField:"Episodes.Tracks", 
                        foreignField:"_id", 
                        @as:"Tracks");

var result = q.ToList();

以上代码将返回List&lt;BsonDocument&gt;

【讨论】:

  • 我只是想加入或使用嵌入的子文档进行子查询
  • @KhairulAlam 修改了我的答案
【解决方案2】:

mickl 的回答会让你使用官方驱动程序,但如果你不喜欢处理 bsondocuments 并且想要某种程度的类型安全,你可以简单地使用 mongodb.entities 库(我是它的作者):

    public class EpisodeWithTracks
    {
        public Track[] Tracks { get; set; }
    }
var pipeline = new Template<Channel, EpisodeWithTracks>(@"
[
    {
        $unwind: '$<Episodes>'
    },
    {
        $lookup: {
            from: '<track_collection>',
            localField: '<Episodes.Tracks>',
            foreignField: '_id',
            as: '<Tracks>'
        }
    }
]")

.Path(c => c.Episodes)
.Tag("track_collection", collectionName)
.Path(c => c.Episodes[0].Tracks)
.PathOfResult(ewt => ewt.Tracks);

var result = DB.Aggregate(pipeline)
               .ToList();

这里是 wiki page 解释它的工作原理。

【讨论】:

猜你喜欢
  • 2015-02-10
  • 2021-04-14
  • 1970-01-01
  • 2016-05-07
  • 1970-01-01
  • 2018-03-09
  • 2021-02-25
  • 2016-08-16
相关资源
最近更新 更多