Reputation: 855
I have user schema
and invitation schema
.
When user search for users I want to return array with object that have property invited
.
const InvitationSchema = new Schema<IInvitation>(
{
sender: {
type: Schema.Types.ObjectId,
ref: 'user'
},
receiver: {
type: Schema.Types.ObjectId,
ref: 'user'
}
}
)
const IUserSchema = new Schema<IUser>(
{
email: {
type: String,
},
invitedUsers: [
{
type: Schema.Types.ObjectId,
ref: 'user'
}
]
}
)
Scenario of my problem:
user1:{
id:userId1,
invitedUsers:[userId2]
}
invitation1:{
id:someId,
sender:userId1,
receiver:userId2
}
users:[
{
id:userId2,
invited:true
},
{
id:userId3,
invited:false
},
]
I also want to paginated users but its not target of the current problem.
I tried some variants with aggregation $addFields but nothing works. The other way to do 10 queries more as the users per page are 10. This is bad idea of course.
Upvotes: 1
Views: 291
Reputation: 16033
This is a nice question. One option is to do it with $lookup
:
id
is included at the invitedUsers
we got from the requesting user.db.users.aggregate([
{$match: {id: {$ne: requestingUserId}}},
{$sort: {id: 1}},
{$skip: 1},
{$limit: 2},
{$addFields: {invitedBy: requestingUserId }},
{
$lookup: {
from: "users",
localField: "invitedBy",
foreignField: "id",
as: "invited"
}
},
{$set: {invited: {$first: "$invited"}}},
{
$project: {
invited: {$cond: [{$in: ["$id", "$invited.invitedUsers"]}, true, false] },
id: 1, _id: 0
}
}
])
See how it works on the playground example
You can also improve the performance by using the $lookup
pipeline to bring only the part you need:
db.users.aggregate([
{$match: {id: {$ne: requestingUserId}}},
{$sort: {id: 1}},
{$skip: 1},
{$limit: 2},
{
$lookup: {
from: "users",
let: {myId: "$id"},
pipeline: [
{$match: {id: "userId1"}},
{$project: {res: {$cond: [{$in: ["$$myId", "$invitedUsers"]}, true, false]}}}
],
as: "invited"
}
},
{$project: {invited: {$first: "$invited.res"}, id: 1, _id: 0}}
])
See how it works on the playground example - lookup-pipeline
Upvotes: 1
Reputation: 141
If you want to check if the invitedUsers
array has some length, then return true, otherwise false, then this could be done with aggregate
User.aggregate([
{
$project: {
_id: 1,
invitedUsers: {
$cond: [
{ $gt: [{ $size:"$invitedUsers" }, 0] },
true,
false,
],
}
}
}
])
explore aggregate here
Upvotes: 0