I am trying to conceptualize how to build an application where users can follow other users and have followers of their own. I know this topic has been covered in some other threads, but what I am really concerned about is determining how to best manage multiple extended references across multiple collections.
For example, when building my application I took into account “what questions am I trying to answer?” to build my collections for effective queries. Since the application will allow users to click a button to see all their followers (just name and profile picture), I thought an extended reference pattern would suffice, only duplicating data that rarely changes. I also wanted to account for any outlier patterns (say if a user has 100 or more followers) to make sure I am keeping my document size down on the rare chance there is an outlier. Example model below…
- Also silly side note, but I am no longer using Mongoose in case someone recommends that I don’t *
User Model
const userSchema = mongoose.Schema(
{
... Other Data...
followers: [
{
userId: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'User'},
userName: { type: String, required: true },
followMeDate: { type: Date, required: true },
userProfilePicture: { type: String, required: true}
}
],
countFollowers: { type: Number, required: true, default: 0 },
hasOutlierFollowers: { type: Boolean, required: true, default: false },
following: [
{
userId: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'User'},
userName: { type: String, required: true },
followingDate: { type: Date, required: true },
userProfilePicture: { type: String, required: true}
}
],
countFollowing: { type: Number, required: true, default: 0 },
hasOutlierFollowing: { type: Boolean, required: true, default: false },
}
)
In the model described above, I am able to accomplish the following:
-
Track the total followers and following when they change with the ‘count’ fields instead of doing some aggregation every time the field is pulled.
-
Limit the number of queries to 1 in order to see what users you are following or who is following you. The UI would display the user’s name and profile picture and can be sorted by most recent followers. Although this is duplicating data, it is duplicating data that will rarely change.
-
Manage collection size and performance since once the first 100 followers / following will be pulled initially. In the rare event that someone has more followers or is following more users there is a separate outliers collection that is storing the data.
Followers / Following Models
const outlierUserFollowersSchema = mongoose.Schema(
{
userId: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'User'},
followers: [
{
userId: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'User'},
userName: { type: String, required: true },
followMeDate: { type: Date, required: true },
userProfilePicture: { type: String, required: true}
}
],
)
const outlierUserFollowingSchema = mongoose.Schema(
{
userId: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'User'},
following: [
{
userId: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'User'},
userName: { type: String, required: true },
followingDate: { type: Date, required: true },
userProfilePicture: { type: String, required: true}
}
],
}
)
So my question is, is this okay? If a user changes their name or picture, I would need to update several collections. What if I had even more collections that had extended references of the user’s name and picture?
Or, if this is really a concern of mine, should I increase the number of users within the main user collection array of following / followers to limit the extra queries?
What if I can’t hold more user data due to size constraints (doubtful, but just curious).