Mongodb:将文档树反向作为视图(使用C#驱动程序)

时间:2018-07-29 17:19:26

标签: c# mongodb aggregation-framework

我正在尝试以下情况(简单的情况):

我有两个看起来像这样的文件(电影有时隙,时隙有电影):

{
   "_id":"5b5dd8932dc7aa1e180f8c23",
   "Name":"Cinema 1",
   "TimeSlots":[
      {
         "Start":"2018-07-29T16:00:00.000Z",
         "End":"2018-07-29T18:30:00.000Z",
         "Movie":{
            "_id":"5b5dd8932dc7aa1e180f8c24",
            "Name":"Movie 1"
         }
      },
      {
         "Start":"2018-07-29T15:00:00.000Z",
         "End":"2018-07-29T17:15:00.000Z",
         "Movie":{
            "_id":"5b5dd8932dc7aa1e180f8c25",
            "Name":"Movie 2"
         }
      }
   ]
}

{
   "_id":"5b5dd8932dc7aa1e180f8c26",
   "Name":"Cinema 2",
   "TimeSlots":[
      {
         "Start":"2018-07-29T18:00:00.000Z",
         "End":"2018-07-29T20:30:00.000Z",
         "Movie":{
            "_id":"5b5dd8932dc7aa1e180f8c24",
            "Name":"Movie 1"
         }
      },
      {
         "Start":"2018-07-29T19:00:00.000Z",
         "End":"2018-07-29T21:15:00.000Z",
         "Movie":{
            "_id":"5b5dd8932dc7aa1e180f8c25",
            "Name":"Movie 2"
         }
      }
   ]
}

我想反转树的结构(所以我有带时隙的电影,这些电影与电影院有联系)。在使用LINQ的C#中,我将执行以下操作:

var movies = cinemas
    .SelectMany(cinema => cinema.TimeSlots)
    .Select(timeSlot => timeSlot.Movie)
    .Distinct(new MovieEqualityComparer())
    .Select(movie =>
    {
        movie.TimeSlots = cinemas
            .SelectMany(cinema => cinema.TimeSlots)
            .Where(timeSlot => timeSlot.Movie.Id == movie.Id)
            .ToList();

        return movie;
    })
    .ToList();

我想知道如何使用聚合函数和聚合管道实现这一目标。我尝试了多个选项,包括$project$unwind$group,但是我似乎无法达到我想要的结果。任何帮助都可以申请。

这是我到目前为止所拥有的:

[  
   {  
      $unwind:{ path:'$TimeSlots' }
   },
   {  
      $unwind:{ path:'$TimeSlots.Movie' }
   },
   {  
      $group:{ 
         _id:'$TimeSlots.Movie._id',
         movies:{  $addToSet:'$TimeSlots.Movie' } }
   },
   { $project: {  movieId: '$_id'} } }
]

直到我的查询与LINQ查询结果相似为止。

1 个答案:

答案 0 :(得分:1)

这里不需要使用双$unwind,因为每个时隙只有一部电影。您可以尝试以下汇总:

db.cinemas.aggregate([
    {
        $unwind: "$TimeSlots"
    },
    {
        $group: {
            _id: "$TimeSlots.Movie._id",
            Name: { $first: "$TimeSlots.Movie.Name" },
            TimeSlots: {
                $push: { 
                    Start: "$TimeSlots.Start", 
                    End: "$TimeSlots.End", 
                    Cinema: { 
                        Name: "$Name", 
                        _id: "$_id" 
                    } 
                }
            }
        }
    }
])

输出:

{
    "_id" : "5b5dd8932dc7aa1e180f8c25",
    "Name" : "Movie 2",
    "TimeSlots" : [
        {
            "Start" : "2018-07-29T15:00:00.000Z",
            "End" : "2018-07-29T17:15:00.000Z",
            "Cinema" : {
                "Name" : "Cinema 1",
                "_id" : "5b5dd8932dc7aa1e180f8c23"
            }
        },
        {
            "Start" : "2018-07-29T19:00:00.000Z",
            "End" : "2018-07-29T21:15:00.000Z",
            "Cinema" : {
                "Name" : "Cinema 2",
                "_id" : "5b5dd8932dc7aa1e180f8c26"
            }
        }
    ]
}
{
    "_id" : "5b5dd8932dc7aa1e180f8c24",
    "Name" : "Movie 1",
    "TimeSlots" : [
        {
            "Start" : "2018-07-29T16:00:00.000Z",
            "End" : "2018-07-29T18:30:00.000Z",
            "Cinema" : {
                "Name" : "Cinema 1",
                "_id" : "5b5dd8932dc7aa1e180f8c23"
            }
        },
        {
            "Start" : "2018-07-29T18:00:00.000Z",
            "End" : "2018-07-29T20:30:00.000Z",
            "Cinema" : {
                "Name" : "Cinema 2",
                "_id" : "5b5dd8932dc7aa1e180f8c26"
            }
        }
    ]
}