Mongo为subdocs聚合$ slice

时间:2014-08-03 02:55:01

标签: mongodb

给出这样的文档:

var user = { 
  _id: '53176dc214d1f0d0ec42ae54',
  friends: [ '53176dc214d1f0d0ec42ae54', '5317766614d1f0d0ec42ae5e' ]
};

我想在聚合管道中返回每个朋友的数量(作为friend_total)以及前10个朋友ID。

到目前为止我有这个返回我想要的数据 - 我需要相当于朋友的$ slice。

{
  $unwind: '$posters',
}, {
$group: {
  _id: '$_id',
  posters:{$push:'$posters'},
  sum: {
    $sum: 1
  }
}

1 个答案:

答案 0 :(得分:4)

不幸的是(在MongoDB 2.6中)聚合管道没有等效的$slice。在MongoDB问题跟踪器中进行upvote / watch的相关功能请求是SERVER-6074: Allow $slice operator in $project

建议的解决方法

有一些不那么美味的解决方法,例如在聚合中返回完整的朋友列表并截断应用程序代码中的数组,或者对find()$slice相关的朋友列表运行多个查询。我的假设是,您的用户平均需要超过10位朋友,因此您希望此查询有效。

我认为你最好的方法是 denormalise 。不要依赖聚合管道来生成前10个朋友ID,而是将这些ID保存到用户文档中的capped array,并在添加/删除新朋友时维护此数组。这确实涉及一些重复的数据,但会快速和简单的查询。同样,您可以使用$inc为每个用户更新friend_count朋友,因为他们会添加/删除朋友。

使用此方法,您将不再需要使用aggregate()来计算朋友数量&前十位朋友,可以使用friend_count进行排序或作为其他查询或报告的基础。

因此,您的用户文档将显示为:

var user = { 
   _id: ObjectId("53176dc214d1f0d0ec42ae54"),
   friends: [ObjectId("53176dc214d1f0d0ec42ae54"), ObjectId("5317766614d1f0d0ec42ae5e")],
   friend_count: 2,
   topten: [ObjectId("53176dc214d1f0d0ec42ae54"), ObjectId("5317766614d1f0d0ec42ae5e")],
};