在数组中聚合 C# groupby

Aggregate C# groupby in array

我有以下结构,我想聚合电影列表以获取所有演员及其图像。

{
"_id" : 1,
"Title" : "Pirates of the Caribbean: The Curse of the Black Pearl",
"Actors" : [ 
    {
        "Name" : "Johnny Depp",
        "NameInMovie" : "Captain Jack Sparrow",
        "ImageUrl" : "Johnny-Depp.png"
    }, 
    {
        "Name" : "Geoffrey Rush",
        "NameInMovie" : "Captain Hector Barbossa",
        "ImageUrl" : "Geoffrey-Rush.png"
    }, 
    {
        "Name" : "Orlando Bloom",
        "NameInMovie" : "Will Turner",
        "ImageUrl" : "Orlando-Bloom.png"
    }
]

},

{
"_id" : 2,
"Title" : "Pirates of the Caribbean: At World's End",
"Actors" : [ 
    {
        "Name" : "Johnny Depp",
        "NameInMovie" : "Captain Jack Sparrow",
        "ImageUrl" : "Johnny-Depp.png"
    }, 
    {
        "Name" : "Geoffrey Rush",
        "NameInMovie" : "Captain Hector Barbossa",
        "ImageUrl" : "Geoffrey-Rush.png"
    }, 
    {
        "Name" : "Orlando Bloom",
        "NameInMovie" : "Will Turner",
        "ImageUrl" : "Orlando-Bloom.png"
    }
]

}

尝试使用 Linq AsQueryable 函数获取结果,但不受支持:

var actors = Movies
.AsQueryable()
.SelectMany(x => x.Actors)
.GroupBy(x => x.Name)
.Select(a => a.First())
.ToList();

如何使用 MongoDB driver2

结果应该喜欢

{"Name" : "Johnny Depp",
"ImageUrl" : "Johnny-Depp.png" }, 
{"Name" : "Geoffrey Rush",
"ImageUrl" : "Geoffrey-Rush.png" }, 
{"Name" : "Orlando Bloom",
"ImageUrl" : "Orlando-Bloom.png" }

已解决

var actors = Movies.AsQueryable()
.SelectMany(x => x.Actors)
.GroupBy(x => new Actor { Name = x.Name, ImageUrl = x.ImageUrl })
.Select(x => x.Key)
.ToList();

这给出了以下查询

[{
    "$unwind": "$Actors"
},
{
    "$project": {
        "Actors": "$Actors",
        "_id": 0
    }
},
{
    "$group": {
        "_id": {
            "ImageUrl": "$Actors.ImageUrl",
            "Name": "$Actors.Name"
        }
    }
},
{
    "$project": {
        "_id": "$_id"
    }
}]

您很接近,但在 $group 中实际选择的属性中大部分缺失:

var results = Movies.AsQueryable()
 .SelectMany( x => x.Actors )
 .GroupBy( x => x.Name )
 .Select( x => new { Name = x.Key, ImgUrl = x.First().ImageUrl })
 .ToArray();

所以 .Select() 实际上需要与您正在使用的语法不同的语法。这为您提供了一个序列化如下的管道:

    [
            {
                    "$unwind" : "$Actors"
            },
            {
                    "$project" : {
                            "Actors" : "$Actors",
                            "_id" : 0
                    }
            },
            {
                    "$group" : {
                            "_id" : "$Actors.Name",
                            "__agg0" : {
                                    "$first" : "$Actors.ImageUrl"
                            }
                    }
            },
            {
                    "$project" : {
                            "Name" : "$_id",
                            "ImgUrl" : "$__agg0",
                            "_id" : 0
                    }
            }
    ],

恕我直言,这并不完全 "optimal",但这就是您使用 LINQ 界面得到的。

还有交替:

var results = Movies.AsQueryable()
 .SelectMany( x => x.Actors )
 .GroupBy( x => new { Name = x.Name, ImgUrl = x.ImageUrl })
 .ToArray();

结果为:

  [
            {
                    "$unwind" : "$Actors"
            },
            {
                    "$project" : {
                            "Actors" : "$Actors",
                            "_id" : 0
                    }
            },
            {
                    "$group" : {
                            "_id" : {
                                    "Name" : "$Actors.Name",
                                    "ImgUrl" : "$Actors.ImageUrl"
                            }
                    }
            }
    ],

它不使用 $first 因此不是 "exactly" 同一件事,但在你的情况下它确实会产生相同的结果,因为 ImgUrl 总是相同的Actor.

上每个 Name 的值