如何使用C#仅从多层嵌入式MongoDB文档中获取具有相应父元素的确切子元素 - c#

尝试使用C#从嵌入式MongoDB文档中获取确切的子文档及其对应的父文档,但查询返回所有子文档以及对应的父文档和其他文档。如何将参数设置为
使用Filter和findOptions获得完全匹配。我的预期结果是频道1->第1集,并且是给定ID的Child Track。
这是我的代码:

// Class
namespace CrudWithMultilvelNestedDoc
{
    public class Channel
    {
        [BsonId]
        [BsonRepresentation(BsonType.String)]
        public string Id { get; set; }
        public string Name { get; set; }
        public Episode[] Episodes { get; set; }
    }

    public class Episode
    {
        [BsonId]
        [BsonRepresentation(BsonType.String)]
        public string Id { get; set; }
        public string Name { get; set; }
        public Track[] Tracks { get; set; }
    }

    public class Track
    {
        [BsonId]
        [BsonRepresentation(BsonType.String)]
        public string Id { get; set; }
        public string Name { get; set; }
        public Like[] Likes { get; set; }
    }

    public class Like
    {
        [BsonId]
        [BsonRepresentation(BsonType.String)]
        public string Id { get; set; }
        public string Name { get; set; }
    }
}

//Code
var chanelId = "5e4606e6ae7b090688671416";
var episodeId = "5e46071d385a672b0cea0f86";
var trackId = "5e460dbe2bc5e70c9cfeac21";

var filter = Builders<Channel>.Filter.And(
             Builders<Channel>.Filter.Where(x => x.Id == chanelId),
             Builders<Channel>.Filter.Eq("Episodes._id", episodeId),
             Builders<Channel>.Filter.Eq("Episodes.Tracks._id", trackId));
var result = collection.Find(filter).ToList();

// Data
{"_id":"5e4606e6ae7b090688671416","Name":"Channel 1","Episodes":[{"_id":"5e46071d385a672b0cea0f86","Name":"Episode 1","Tracks":[{"_id":"5e460dbe2bc5e70c9cfeac21","Name":"Trak 1","Likes":[{"_id":"5e4635d41f949d43a8194790","Name":"Like 1"},{"_id":"5e464e1ccfa17a25181234f6","Name":"Like 2"},{"_id":"5e464e94776dc808383326d5","Name":"Like 3"}]},{"_id":"5e4612d60747a2121870c815","Name":"Trak 2","Likes":[]}]},{"_id":"5e460851d29c1b3df4d27b7d","Name":"Episode 2","Tracks":[{"_id":"5e460e307ca6843758ce814e","Name":"Trak 1","Likes":[{"_id":"5e4686aa2813d41fa428b621","Name":"Like 1"}]}]}]}

如何使用C#仅从多层嵌入式MongoDB文档中获取具有相应父元素的确切子元素 - c#

参考方案

由于您的文档是多层的,因此必须使用$filter运算符。在C#中,使用LINQ进行此类查询很容易,因为它会在后台自动生成$filter并保留强类型的查询:

var q = from channel in mongoDBCollection.AsQueryable()
        from episode in channel.Episodes
        select new Episode()
        {
            Id = episode.Id,
            Name = episode.Name,
            Tracks = episode.Tracks.Where(x => x.Id == trackId)
        };

var query = q.Where(x => x.Tracks.Any());
var result = query.ToList();

MongoDB .NET驱动程序生成的聚合管道如下所示:

{ 
    "aggregate" : "col", 
    "pipeline" : [
        { "$unwind" : "$Episodes" }, 
        { 
            "$project" : { 
                "Id" : "$Episodes._id", 
                "Name" : "$Episodes.Name", 
                "Tracks" : { 
                    "$filter" : { 
                        "input" : "$Episodes.Tracks", 
                        "as" : "x", 
                        "cond" : { "$eq" : ["$$x._id", "5e460dbe2bc5e70c9cfeac21"] } 
                    } 
                }, 
                "_id" : 0 
            } 
        }, 
        { 
            "$match" : { 
                "Tracks" : { 
                    "$ne" : null, 
                    "$not" : { "$size" : 0 } 
                } 
            } 
        }], 
    "cursor" : { }, 
}

编辑:

为了提高上述查询的性能,您可以考虑通过添加channel语句在where级别进行过滤:

from channel in mongoDBCollection.AsQueryable()
where channel.Id == channelId

编辑:当您也想返回Channel时,它会变得有些棘手。我的建议是返回一个包含ChannelEpisode的异常类型,并将它们组合在内存中,因为它将允许您在数据库端运行大多数筛选并获得最佳性能:

var q = from channel in mongoDBCollection.AsQueryable()
        where channel.Id == "5e4606e6ae7b090688671416"
        from episode in channel.Episodes
        select new 
        {
            Channel = new Channel(){ Id = channel.Id, Name = channel.Name},
            Episode = new Episode()
            {
                Id = episode.Id,
                Name = episode.Name,
                Tracks = episode.Tracks.Where(x => x.Id == trackId)
            }
        };

var query = q.Where(x => x.Episode.Tracks.Any());
var result = query.ToList();

当回复有时是一个对象有时是一个数组时,如何在使用改造时解析JSON回复? - java

我正在使用Retrofit来获取JSON答复。这是我实施的一部分-@GET("/api/report/list") Observable<Bills> listBill(@Query("employee_id") String employeeID); 而条例草案类是-public static class…

Mongo汇总 - javascript

我的收藏中有以下文件{ "_id": ObjectId("54490b8104f7142f22ecc97f"), "title": "Sample1", "slug": "samplenews", "cat": …

如何在Wiremock中为JUNIT匹配精确的json - java

我正在使用Wiremock在Spring启动应用程序中模拟Junit的REST服务。我的问题是,我无法匹配多个匹配模式。 Junit.javaStringValuePattern pattern = WireMock.matching(".*"); givenThat(post(urlEqualTo("/softwares�…

Div单击与单选按钮相同吗? - php

有没有一种方法可以使div上的click事件与表单环境中的单选按钮相同?我只希望下面的div提交值,单选按钮很丑代码输出如下:<input id="radio-2011-06-08" value="2011-06-08" type="radio" name="radio_date&#…

使用Json.NET反序列化复杂对象 - c#

我需要反序列化从grogle maps api返回的json:{ "destination_addresses": [ "Via Medaglie D'Oro, 10, 47121 Forlì FC, Italia", "Via Torino, 20123 Milano, Italia",…