Reputation: 165
My desired outcome is check common ids and their count between friends. One is closed friends count and another one is normal friends count.
Here data is the list of my friends and user is me.
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)
}
By performing two separate queries i am getting proper result but i want to combine these two queries.
One more problem with above one is, output of result1 is not giving promised output for last fetching(or matching).
Edit:-
{ "_id" : 1, "friends" : [2,3,4], "closedFriends":[5,6,7] }
{ "_id" : 2, "friends" : [ 1,3,5 ], "closedFriends" : [4,6,7] }
In the above database the common friends between 1 and 2 is 3 and closedFriends are 6 and 7. The desired output is cfcount is 2 and fcount is 1 along with 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}] }
Here along with count I want to include filed 'name' and 'score' in aggregated output.
Upvotes: 0
Views: 198
Reputation: 4285
The aggregation framework can replace all your Javascript calculations (your for loop counting), and thus eliminate o(2n) aggregational computations you did, into only one 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',
]
}
}
}
},
])
}
Upvotes: 1