如何为单个集合的两个不同输出聚合两个嵌套数组?

时间:2018-04-01 14:15:48

标签: mongodb mongoose mongodb-query aggregation-framework

我想要的结果是检查常见的ID以及他们在朋友之间的数量。一个是关闭的朋友计数,另一个是正常的朋友计数。

这里的数据是我的朋友列表,用户就是我。

async function uinfo(data, user){
  const arr = []
    for (const i of data) {
      await Profile.aggregate([{"$match": {"_id": {"$in": [user, i._id]}}}, {"$unwind": "$list.closedFriends"}, {"$group": {_id: "$list.closedFriends.id", count: {$sum: 1}}}, {$match: {count: 2}}, {$project: {_id: 1}}], function(err, result){
          if(result.length >= 1){
            i.cfcount = result.length
          }
          else{
            i.cfcount = 0
          }
      })
      await Profile.aggregate([{"$match": {"_id": {"$in": [user, i._id]}}}, {"$unwind": "$list.friends"}, {"$group": {_id: "$list.friends.id", count: {$sum: 1}}}, {$match: {count: 2}}, {$project: {_id: 1}}], function(err, result1){
          if(result1.length >= 1){
            i.fcount = result1.length
          }
          else{
            i.fcount = 0
          }
      })
      arr.push(i)
    }
    console.log(arr)
    return await Promise.all(arr)
}

通过执行两个单独的查询,我得到了正确的结果,但我想结合这两个查询。

上面的一个问题是,result1的输出没有给出最后一次提取(或匹配)的承诺输出。

修改: -

{ "_id" : 1, "friends" : [2,3,4], "closedFriends":[5,6,7] }
{ "_id" : 2, "friends" : [ 1,3,5 ], "closedFriends" : [4,6,7] }

在上面的数据库中,1和2之间的常见朋友是3,closedFriends是6和7.所需的输出是cfcount是2,fcount是1和ids。

EDIT2: -

{ "_id" : 1, "friends" : [{id:1, name:'john', score:0}, {id:2, name:'john', score:0}, {id:3, name:'john', score:0}], "closedFriends":[{id:8, name:'john', score:0}, {id:4, name:'john', score:0}, {id:5, name:'john', score:0}] }
{ "_id" : 2, "friends" : [{id:2, name:'john', score:0}, {id:7, name:'john', score:0}, {id:3, name:'john', score:0} ], "closedFriends" : [{id:1, name:'john', score:0}, {id:9, name:'john', score:0}, {id:8, name:'john', score:0}] }

除此之外,我想要包括已提交的姓名'和'得分'在汇总输出中。

1 个答案:

答案 0 :(得分:1)

聚合框架可以替换您的所有Javascript计算(用于循环计数),从而消除您所做的 o(2n)聚合计算,只消除一个 O(1)

function uinfo(data, user){
    let mainUser = db.Profile.findOne({_id: user});
    let userIds = Array.from(data, user => user.id);
    return Profile.aggregate([
    {$match: {'_id': {$in: userIds}}},
    {
        $project: {
            '_id' : 1,
            'fcount': {
                $size: {
                    $setIntersection: [
                        mainUser.friends,
                        '$friends',
                    ]
                }
            },
            'cfcount': {
                $size: {
                    $setIntersection: [
                        mainUser.closedFriends,
                        '$closedFriends',
                    ]
                }
            }
        }
    },
    ])
}
相关问题