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:
- There are 3 users with ids - userId1, userId2, userId3
- User1 sends invitation to User2. So current db becomes:
user1:{
id:userId1,
invitedUsers:[userId2]
}
invitation1:{
id:someId,
sender:userId1,
receiver:userId2
}
- Here User1 make a user search request to the server and receive:
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.
CodePudding user response:
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
CodePudding user response:
This is a nice question. There is a "trick" you can do here with $lookup
:
- The first 4 steps here are regarding your pagination, returning only the number of documents you need, after sorting, skipping, limiting and remove the user who request the search.
- Then we use the $lookup` to add the details of the requestingUserId, including the list of invited user ids on each one of our selected documents.
- Now all is left is to check for each document if its own
id
is included at theinvitedUsers
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