【问题标题】:How do I group by in mongodb to produce a list of objects?如何在 mongodb 中分组以生成对象列表?
【发布时间】:2013-01-10 06:29:45
【问题描述】:

我有这样的数据,

{
    meta: {
        artist: "artist",
        album: "album",
        year: 2008
    }
}

我想对艺术家进行 SQL 组的等效操作,以使用 mongodb 聚合生成带有 { album: album, year: year } 的对象列表。

我有这个查询,这几乎是我想要的,但我认为它不是正确的方法。

db.pending.aggregate( [ 
    { $project: 
      { 'meta.artist': 1, 'meta.album': 1, 'meta.year':1 } 
    }, 
    { $group: 
      {
       '_id': 
         { artist: '$meta.artist', album: '$meta.album', 
             year: { $year: '$meta.year'}  
         } 
      }
    }
] )

【问题讨论】:

    标签: javascript node.js mongodb


    【解决方案1】:

    我认为您需要$addToSet 运算符:

    db.test.aggregate(
      { $project:
        { 'meta.artist': 1
        , 'meta.album': 1
        , 'meta.year': 1 }
      }
      , { $group:
          { _id: '$meta.artist'
          , albums: {
            $addToSet: {
              album: '$meta.album'
            , year: '$meta.year' }
          }
        }
      }
    )
    

    【讨论】:

      【解决方案2】:

      我认为您可以通过这样的聚合框架执行以下操作:

      db.pending.aggregate(
        {$group: {_id: '$artist', albums: {$push: {album: '$album', year: '$year'}}}}, 
        {$sort: {_id: 1}}
      );
      

      或者你可以通过 map reduce 函数来做到这一点:

      var mapFunction = function() {
                             emit(this.meta.artist, {album: this.meta.album, year: this.meta.year});
                         };
      
      var reduceFunction = function(artistId, albumValues) {
                           var reducedObject = {
                                      artisId: artistId,
                                      albums: []};
      
                          albumValues.forEach( function(albumValue) {
                                         reducedObject.albums.push(
                                             {album: albumValue.album,
                                             year: albumValue.year}
                                              );
                                         });
                              return reducedObject;
      };
      
      db.pending.mapReduce(
                           mapFunction,
                           reduceFunction,
                           { out: { inline: 1 } }
                         )
      

      我认为你也不能通过 SQL group by query 做你想做的事。这将返回类似于 {_id: "artisName", values[{album: 'album1', year: 'year1'}, {album: 'album2', year: 'year2'}]}

      的结果

      【讨论】:

      • 是否可以使用聚合而不是 mapReduce 来做到这一点?
      • 可能有,但我没有玩过聚合框架,更喜欢 map reduce 而不是其他的,因为它现在有更好的文档记录,而且它更具可扩展性,如以下帖子 stackoverflow.com/questions/12337319/… 所述/跨度>
      • 最后添加了如何使用聚合框架来做到这一点。
      猜你喜欢
      • 1970-01-01
      • 2018-11-09
      • 1970-01-01
      • 1970-01-01
      • 2021-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-29
      相关资源
      最近更新 更多