Reputation: 232
I want to get mutual (so from all users the user I have the most shared followers with (we both follow the same user) sorted by that count). followers from my database scheme (mongoDB) with an aggregation function.
user scheme:
let User = new mongoose.Schema({
uid: {
type: String,
require: true,
unique: true
},
followers: [String],
following: [String]
})
where followers/following is an array of UID's
I've tried this:
let me = await User.findOne({uid: uid})
if (me) {
console.log(me.followers)
let mutual = await User.aggregate([
// Match documents that contain the elements
{ "$match": {
"followers": { "$in": me.followers }
}},
// // De-normalize the array field content
{ "$unwind": "$followers" },
// Match just the elements you want
{ "$match": {
"followers": { "$in": me.followers }
}},
// Count by the element as a key
{ "$group": {
"_id": "$name",
"mutual": { "$sum": 1}
}}
])
if (mutual) {
console.log('mutual', mutual)
}
}
but this doesn't give the correct count
Upvotes: 0
Views: 375
Reputation: 28356
You can use $filter
and $size
instead of unwinding the followers for each person. You can also do this with an $lookup
instead of 2 client-side queries.
The stages in the below pipeline:
matched
arrayuid
, and for commonFollowers:
followers
array, keeping only those entries that match the user in question[
{"$match": {"uid": uid}},
{
"$lookup": {
"from": "User",
"localField": "followers",
"foreignField": "followers",
"as": "matched"
}},
{"$unwind": "$matched"},
{"$match": {"$expr": {"$ne": ["$matched.uid", "$uid"]}}},
{"$project": {
"_id": 0,
"uid": "$matched.uid",
"commonFollowers": {
"$size": {
"$filter": {
"input": "$matched.followers",
"cond": {
"$in": [
"$$this",
"$followers"
]
}}}}}},
{"$sort": {"commonFollowers": -1}}
])
Upvotes: 1