Reputation: 138
I was wondering what is the best scheme for user/notifications kind of scenario like the following:
1 | 01-04-2020 | X | John liked your post2
2 | 01-03-2020 | X | Mike and 9 other persons liked your post1
3 | 01-02-2020 | | Rose and 2 other persons liked your post1
4 | 01-01-2020 | | Bernard liked your post1
x = notification has not been read by the user yet
post1 = the same post in all the notifications
Let's say I have a Notification collection like:
_id: ObjectID
receiver: ObjectID (User)
sender : ObjectID (User)
type: String ("post", "comment", etc...)
typeID: ObjectID (Post, Comment, etc...)
message: String
isRead : Boolean
timestamp: Date
A User collection like :
_id: ObjectID
username: String
.
.
.
email: String
A Post Collection like :
_id: ObjectID
postedBy: ObjectID (User)
.
.
.
content: String
A Like collection like :
_id: ObjectID
type: String ("post", "comment", etc...)
typeID: ObjectID (Post, Comment, etc...)
likedBy: ObjectID (User)
I want the user to be able to see all his previous notifications as well as the notifications he hasn't read yet. If the user has several notifications for the same post (X people liked his post since the last time he checked his notifications), I want to group them as 1 notification (I will mark all of them as read once he read that one grouped notification).
How can I do that?
Please let me know if you need more information or if I am being unclear.
Thanks
Edit:
I'm having a hard trying to figure out how to aggregate those notifications. I think I need some kind of read date marker as well to group the notifications that were grouped and read at the same time, but maybe I need another collection to store the grouped notifications?
Notification.aggregate([
{
$group: {
_id: {
typeID : "$typeID",
receiver: "$receiver",
isRead: "$isRead"
// maybe something with a read date?
},
count: {$sum: 1}
}
}
])
Upvotes: 3
Views: 1037
Reputation: 4352
I guess this article at Mongo University is a relevant answer to your question.
Use at least two collections: users
and notifications
also, you your users _id
field isn't something like name
and you'll allow them to be renamed, then it's perfect to have 3-rd collection likes
, instead making likes as a embedded documents in array, like this:
User's schema:
_id: ObjectID,
likes: [{
_id: ObjectID //like_id,
other: "field"
}]
Notifications:
_id: ObjectID
receiver: ObjectID (User)
sender : ObjectID (User)
type: {
type: String,
enum: ["Post", "Comment"] /** Use enum for avaliable values */
},
typeID: {
type: ObjectID, /** It's better if every ID field have an index */
index: true,
unique: true
}
message: String
isRead : Boolean
timestamp: {
type: Date,
default: Date.now /** Don't forget about default values, but check my advice below about $timestamps */
}
Not sure that timestamp field is needed for you, as for me, it's
better to use {timestamps: true}
option.
Also, every field with ObjectID
should be indexed, it you needed
this fields for aggregation
framework. It's a perfect performance
case for $lookup
I want the user to be able to see all his previous notifications as well as the notifications he hasn't read yet.
You needed a compound
index for this, like {sender:1, createdAt: -1, isRead: 1}
I want to group them as 1 notification (I will mark all of them as read once he read that one grouped notification).
This is a job for aggregation
framework, via:
{
$match: { query_criteria },
},
{
$group: { query_group_by $notification.typeID }
}
So your schema is fine, it's possible to do that. By the way, to test your own queries, you could use MongoPlayground, instead of production DB.
As for the likes
schema, it's for you to decide, but maybe it's better to have them as an embedded (child) documents, like:
Post
_id: ObjectID
postedBy: ObjectID (User)
likes: [{
/** Likes Sub-schema */
}]
content: String
Take a look at sub-schema pattern in mongoose.
Hope it will helps you!
Upvotes: 5