使用三层层次结构作为输出进行聚合

时间:2014-08-26 11:18:08

标签: mongodb

我正在尝试使用MongoDB在Node.JS中创建一个简单的mediaserver用于它的后端。我将以下列方式将轨道元数据存储在MongoDB数据库中:

{
    "_id" : ObjectId("53fadfb28024a9b42079820d"),
    "title" : "Welcome To The Machine",
    "artist" : [
            "Pink Floyd"
    ],
    "albumartist" : [ ],
    "album" : "Wish You Were Here",
    "year" : "1975",
    "track" : {
            "no" : 2,
            "of" : 5
    },
    "genre" : [
            "Rock"
    ],
    "disk" : {
            "no" : 0,
            "of" : 0
    },
    "duration" : 446,
    "filelocation" : "F:\\mediaserver\\Pink Floyd\\Wish You Were Here\\02 - Welcome To The Machine.m4a"
}

我想以下列方式提取艺术家,专辑和曲目信息:

[
    {
        artist: [ "someartist" ],
        albums: [
                    {
                        title: "AlbumTitle",
                        tracks: [ "trackTitleOne", "trackTitleTwo" ]
                    }
                ]
    },
    {
        artist: [ "second artist" ],
        albums: [
                    {
                        title: "AlbumTitle 2",
                        tracks: [ "trackTitleOne", "trackTitleTwo" ]
                    }
                ]
    }
]

我一直在mongo shell中尝试不同的语句,而我最接近的是

db.testData.aggregate([
                          {

                           $group: {
                                    _id: "$artist",
                                    albums: { $addToSet: { title: "$album" } }
                                    }
                          }
                     ])

产生

{ "_id" : [ "Dave Brubeck" ], "albums" : [ { "title" : "Time Out" } ] }
{ "_id" : [ "Ian Hunter" ], "albums" : [ { "title" : "Welcome To The Club (disc 2)" },    { "title" : "Welcome To The Club (disc 1)" } ] }
{ "_id" : [ "The Band" ], "albums" : [ { "title" : "The Last Waltz <Complete Edition> (disc 2)" } ] }
{ "_id" : [ "Pink Floyd" ], "albums" : [ { "title" : "Wish You Were Here" }, { "title" : "Dark Side Of The Moon" } ] }

但正如您所看到的,该输出不包含任何曲目信息。我觉得像

这样的东西
 db.testData.aggregate([
                       {
                           $group: {
                                    _id: "$artist",
                                    albums: { $addToSet: { title: "$album", tracks: { $push: "$title" } } }
                           }
                       }
                       ])

可以做到这一点,但遗憾的是,这给我一个错误:

assert: command failed: {
    "errmsg" : "exception: invalid operator '$push'",
    "code" : 15999,
    "ok" : 0
} : aggregate failed
Error: command failed: {
    "errmsg" : "exception: invalid operator '$push'",
    "code" : 15999,
    "ok" : 0
} : aggregate failed
at Error (<anonymous>)
at doassert (src/mongo/shell/assert.js:11:14)
at Function.assert.commandWorked (src/mongo/shell/assert.js:244:5)
at DBCollection.aggregate (src/mongo/shell/collection.js:1149:12)
at (shell):1:13
2014-08-26T13:08:59.094+0200 Error: command failed: {
    "errmsg" : "exception: invalid operator '$push'",
    "code" : 15999,
    "ok" : 0
} : aggregate failed at src/mongo/shell/assert.js:13

我也一直在检查这些手册,但它们似乎并没有包含任何关于如何执行这样一个复杂查询的线索。

(对不起,如果我在这里打破任何不成文的规则,这是我的第一篇文章。)

1 个答案:

答案 0 :(得分:0)

我尝试用双$group构建它,因为为什么不:

 db.test.aggregate({$group : {_id: "$album" ,
                              artist: {$addToSet: "$artist"},
                              tracks:{$addToSet:"$title"}}},
                   {$group: {_id : "$artist",
                             albums:{$push: "$$ROOT"}}})

第一个制作专辑文档,第二个将艺术家分组。它生成表格

的文件
{ "_id" : [ [ "Pink Floyd" ] ],
          "albums" : [ { "_id" : "New Album",
                         "artist" : [ [ "Pink Floyd" ] ], 
                          "tracks" : [ "Testtitle" ] },
                       { "_id" : "Wish You Were Here",
                         "artist" : [ [ "Pink Floyd" ] ],
                         "tracks" : [ "Testtitle", 
                                      "Welcome To The Machine" ] } ] }

添加项目

{$project:{artist:"$_id","albums._id":1,"albums.tracks":1,_id:0}}

它产生

{   "artist" : [["Pink Floyd"]],
    "albums" : [{"_id" : "New Album",
                 "tracks" : ["Testtitle"]},
                {"_id" : "Wish You Were Here",
                 "tracks" : ["Testtitle",
                             "Welcome To The Machine"]
                }]
}

不完全是您想要的(我无法将相册数组中的_id重命名为title,而不会严重行为不端,艺术家是双阵列)但也许是启动。


编辑:Trond Humborstad的最终解决方案

{ $group: { _id: {album: "$album", artist: "$artist"},
          tracks: { $addToSet: { id: "$_id", title: "$title" }}}},                 
{ $group: { _id: "$_id.artist",
           albums: { $addToSet: { title: "$_id.album", tracks: "$tracks" }}}}