2017-05-28 78 views
0

人口稠密的价值我真的会appreicate具有以下情形的帮助。 我有这样的模式:骨料与猫鼬

var Song = Schema({ 
    author: { type: Schema.Types.ObjectId, ref: 'user' }, 
    title: String, 
    photo: String, 
    date: Date, 
    duration: Number, 
    views: [{ type: Schema.Types.ObjectId, ref: 'user' }], 
    likes: [{ type: Schema.Types.ObjectId, ref: 'user' }] 
}) 


var User = mongoose.Schema({ 
    email:String, 
    name:String, 
    gender: String, 
    birthday: String, 
    city: String, 
    continent: String 
}); 

我想写一个查询,将呈现给用户的总喜欢和他的歌群组检视每个大陆。例如:

{continent: 'Asia', views:4000, likes:5000}, 
{continent: 'Europe', views:3200, likes:4500} 

此外,我会很高兴地知道,如果它被认为是“重查询”,也许,如果它是一个聪明的想法等,并视图保存为大陆用户id的组合。

回答

1

不是.populate()(这是一个“客户”端操作)所需的服务器,其中.aggregate()是“服务器”端操作上的数据“加盟”。这是$lookup运营商是什么:

这也可能是最优化,以$map“类型”和$concatArrays先做$lookup

Song.aggregate([ 
    { "$project": { 
    "author": "$author", 
    "data": { 
     "$concatArrays": [ 
     { "$map": { 
      "input": "$views", 
      "as": "el", 
      "in": { "type": "views", "_id": "$$el" } 
     }}, 
     { "$map": { 
      "input": "$likes", 
      "as": "el", 
      "in": { "type": "likes", "_id": "$$el" } 
     }} 
     ] 
    } 
    }}, 
    { "$unwind": "$data" }, 
    { "$lookup": { 
    "from": "users", 
    "localField": "data._id", 
    "foreignField": "_id", 
    "as": "data._id" 
    }}, 
    { "$unwind": "$data._id" }, 
    { "$group": { 
    "_id": { 
     "author": "$author", 
     "continent": "$data._id.continent" 
    }, 
    "views": { 
     "$sum": { "$cond": [ { "$eq": [ "$data.type", "views" ] }, 1, 0 ] } 
    }, 
    "likes": { 
     "$sum": { "$cond": [ { "$eq": [ "$data.type", "likes" ] }, 1, 0 ] } 
    } 
    }} 
], function(err, results) { 

}) 

之前,您这样做“阵列加入”在一开始,因为在一些指向你想要的“喜欢”和因为如果我们试图单独对付他们与后来的$unwind操作单个阵列中的“意见”(你以对“大陆”的数值“计数”需要),那么你结束因为一个数组的内容会乘以另一个数组的内容。

所以惠斯特“加盟”,我们纪念了“型”,因为它们不再是单独的领域,我们仍然需要“喜欢”和计数“意见”之间distinquish。

$lookup操作能够在大多数现代版本中使用“平面”数组,但不能与第一阶段构建的“文档数组”一起使用。只需$unwind首先处理。

一旦$lookup完成,此表单中的结果将是包含在"data._id"路径中的每个结果的单个元素数组。为了继续处理我们$unwind再次。

最后是你$group,其中“复合键”用于从联合数据中获得的“作者”和“大陆”值。为了计数,“喜欢”和“视图”中的每一个都应用于$cond表达式,其是三元(if/then/else)运算符。给定第一个参数中的条件,如果条件为true,则返回第二个参数值或当第三个参数为false时。

这些表达式的结果被传递到$sum积累,从而当条件相匹配的正计数被返回并积累的分组密钥。


所有聚合是“重”的操作,并进行“连接”真的认为更“重”。

在大量的案例有什么不对您的应用程序在运行时执行这种类型的查询。这真的归结为,如果这是以有效的速度运行你的数据或不。如果数据足够大以至于这些操作需要花费过多时间,那么您应该通过将这些汇总数据累积在单独的记录中进行“预汇总”。在这种情况下,增加每个作者每个大陆的“喜欢”或“观看”计数等。

+0

谢谢SOM多,这是我有生以来收到的最好的答案 - 所以乐于助人:-) –

+0

再多一次questsion,是有可能组,以便在大陆的结果将是这样的: { 作者:UserObject, viewsandLikes:{大洲:“亚洲”,意见:1000,喜欢:2000}, {大陆:“欧洲,意见:0,喜欢:0}, {大陆:”美国,意见:10 ,like:20}, } } –