Proper Mongoose Subdocument Relation


Proper Mongoose Subdocument Relation



I have a model


const userSchema = Schema({
username: String
})

const invitationSchema = Schema({
decision: String,
user: {
type: Schema.ObjectId,
ref: 'User'
}
})

const groupSchema = Schema({
name: String,
invitations: [{
type: Schema.ObjectId,
ref: 'Invitation'
}]
})



So the basic model looks like


group {
name
invitations [
user {
username
}
]
}



As user i would like to get all groups that i have invitations for


const user = getContextUser()
Group.find({
'invitations.user': user._id
})



But it doesn't seem to work, i could use a property group referring to Group schema in Invitation model, but i want the good way approach


Group


Invitation



How to i get all groups that user have invitations for



Don't look at this below, this is my actual model representation in json, just in case




// GROUP
{
"_id": ObjectId("5b3901dd9a8c0e6790af4ee8"),
"image": {
"filename": "8547aa2a-d16c-4da7-8d51-6c9bf8038037.jpg",
"width": 236,
"height": 156
},
"geolocation": {
"coordinates": [-152.1997, -24.7718],
"type": "Point"
},
"invitations": [
ObjectId("5b3901dd9a8c0e6790af4eea"),
ObjectId("5b3901dd9a8c0e6790af4eeb"),
ObjectId("5b3901dd9a8c0e6790af4eec"),
ObjectId("5b3901dd9a8c0e6790af4eed"),
ObjectId("5b3901dd9a8c0e6790af4eee"),
ObjectId("5b3901dd9a8c0e6790af4eef"),
ObjectId("5b3901dd9a8c0e6790af4ef0")
],
"messages": ,
"title": "id in magnam",
"description": "Cupiditate doloremque sunt placeat beatae et ex rerum nisi voluptate. Aliquam hic voluptas quas iure assumenda rerum aut. Quisquam vero beatae odit aut ut quod magnam.",
"created_at": ISODate("2018-07-01T16:31:25.237Z"),
"created_by": ObjectId("5b3901dc9a8c0e6790af4ee1"),
"color": "#347303",
"require_people_decision": true,
"is_public": true,
"start_date": ISODate("2019-03-18T20:05:03.116Z"),
"end_date": ISODate("2019-03-18T20:05:03.116Z"),
"location": "25498 Berniece Prairie",
"__v": 1
}

// INVITATION
{
"_id": ObjectId("5b3901dd9a8c0e6790af4eea"),
"created_at": ISODate("2018-07-01T16:31:25.348Z"),
"have_seen": false,
"user": ObjectId("5b3901dc9a8c0e6790af4ee0"),
"__v": 0
}

// USER
{
"_id": ObjectId("5b3901dc9a8c0e6790af4ee0"),
"avatar": {
"filename": "d438befb-2ea3-4582-b6bf-b8dd3b9bcf66.jpeg",
"width": 200,
"height": 200
},
"phone": "5556106679",
"password": "$2b$10$mbx9Yhj5mAKyVxwmxcumaepXYkCTiF/9VM2KJRARZkPOVN300pKc.",
"version": 1,
"friends": ,
"__v": 0
}





can you please post your sample collection
– Anthony Winzlet
Jul 1 at 16:02





@AnthonyWinzlet what do you mean by sample collection? i have posted schema
– Medet Tleukabiluly
Jul 1 at 16:11





data you want to be returned after the query... you can copy it from mongo shell or any GUI you are using
– Anthony Winzlet
Jul 1 at 16:12






i want the groups, filtered by user which is in group's invitation
– Medet Tleukabiluly
Jul 1 at 16:13





I understood that but your query seem to be correct and that's why I am asking for your collection
– Anthony Winzlet
Jul 1 at 16:14




1 Answer
1



You can try below aggregation


Group.aggregate([
{ "$lookup": {
"from": Invitations.collection.name,
"let": { "invitations": "$invitations" },
"pipeline": [
{ "$match": { "$expr": { "$in": [ "$_id", "$$invitations" ] } } }
],
"as": "invitations"
}},
{ "$match": { "invitations.user": user._id } }
])



or this


Group.aggregate([
{ "$lookup": {
"from": Invitations.collection.name,
"let": { "invitations": "$invitations" },
"pipeline": [
{ "$match": {
"user": user._id,
"$expr": { "$in": [ "$_id", "$$invitations" ] }
}}
],
"as": "invitations"
}},
{ "$match": { "invitations.user": user._id } }
])



And the last one which I think is the best option to start with User collection


User


User.aggregate([
{ "$match": { "_id": user._id }},
{ "$lookup": {
"from": Groups.collection.name,
"let": { "userId": "$_id" },
"pipeline": [
{ "$match": { "$expr": { "$eq": [ "$created_by", "$$userId" ] }}}
],
"as": "groups"
}}
])





is Invitations.collection.name intentional? why not just 'Invitation'
– Medet Tleukabiluly
Jul 1 at 16:46



Invitations.collection.name


'Invitation'





you need to replace it by your collection name... It might be invitations or Invitation or whatever it is
– Anthony Winzlet
Jul 1 at 16:47



invitations


Invitation





This approach it too hard to modify, operation is typical tho, maybe there's a simpler solution...?
– Medet Tleukabiluly
Jul 1 at 18:34






see the updated answer
– Anthony Winzlet
Jul 1 at 18:50





Altho this answers my initial question, the approach ain't perfect, the returning result will not contain all Invitations from invitations property, only the filtered ones
– Medet Tleukabiluly
Jul 3 at 19:48


invitations






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

How to make file upload 'Required' in Contact Form 7?

Rothschild family

amazon EC2 - How to make wp-config.php to writable?