Mongoose - Reference a field from another table - node.js

I have two tables: Post and User and I want to reference the User name in the Post table.
I can reference the ID but I also need the name.
User model:
const userSchema = new mongoose.Schema({
username: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
})
module.exports = mongoose.model("User", userSchema)
Post model:
const { ObjectId } = mongoose.Schema.Types
const postSchema = new mongoose.Schema({
title: {
type: String,
required: true,
},
author: {
type: ObjectId,
ref: "User",
},
})
module.exports = mongoose.model("Post", postSchema)
In the doc they said:
Note: ObjectId, Number, String, and Buffer are valid for use as refs.
However, you should use ObjectId unless you are an advanced user and
have a good reason for doing so.
However I couldn't find an example on how I can do this.

Related

how to set a default image to a user with mongoose y node.js

I am creating an application with some functionality similar to twitter where the user posts text and images.
I want to give the user a default profile picture in case he doesn't have one, but I'm not sure how to do it.
I created a schema image where I wrote the following code but I don't know how to continue to make what I want to implement work:
'use strict';
const mongoose = require('mongoose');
const imageSchema = mongoose.Schema({
photo: { type: Array, default: ['https://wallpapers-clan.com/wp-content/uploads/2022/06/cute-pusheen-pfp-1.jpg'] }
});
This is the user schema I created:
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const {Schema} = mongoose;
const saltRounds = 10;
const userSchema = new mongoose.Schema({
name: { type: String, require: true },
username: { type: String, unique: true },
email: { type: String, unique: true },
password: { type: String, require: true },
salt: { type: String, require: true },
followers: [{
type: 'ObjectId',
ref: 'User'
}],
following: [{
type: 'ObjectId',
ref: 'User'
}],
posts: [
{
type: 'ObjectId',
ref: 'Post'
}
]
}, { timestamps: true });
I created a schema image but I'm not sure if I'm on the right track
If your users can only have one profile picture it's not necessary to create a new schema just for the profile picture. You could store the image as an URL in the user schema, that way when you load the user's document you also get their profile picture.
You could add the following field to your existing user schema:
profilePicture: {
type: String,
default: 'https://example.com/cute-pusheen.jpg' // Add a default value
},
In this case if you don't specify an image when creating the user the defualt value will be used.

How do I fetch User post on user timeline?

I have a database containing 3 collections [Users (contains registered users), Userpost (contains the post of the registered users) while Profile (contains their individual profile)].
I was able to link the Profile and Users Schemas to the Userpost Schema with their ObjectId.
What I know at present is how to fetch the Userpost and populate the User and Profile.
What I want to do is to fetch all the post of a single registered user his/her timeline.
What I have tried to the add the Userpost and Profile Schemas to the UserSchema by the ObjectId but each time I make a post, the Userpost on the User collection is always an empty array.
Below are my Schemas please
User Schema
const userSchema = new Schema({
username: {
type: String,
required: true
},
roles: {
User: {
type: Number,
default: 2001
},
Mentor: Number,
Admin: Number
},
password: {
type: String,
required: true
},
userID: {
type: String,
required: true
},
refreshToken: String
});
const User = mongoose.model('user', userSchema);
module.exports = User;
Profile Schema
const ProfileSchema = new Schema({
lastname: {
type: String,
required: true,
},
firstname: {
type: String,
required: true,
},
othernames: {
type: String,
required: true,
},
countries: {
type: String,
required: true,
},
phones: {
type: String,
required: true,
},
User: [{
type: Schema.Types.ObjectId,
ref: 'user',
required: true,
}],
});
const Profile = mongoose.model('profile', ProfileSchema);
module.exports = Profile;
UserPost Schema
const UserpostSchema = new Schema({
post: {
type: String,
required: true
},
Profile: [{
type: Schema.Types.ObjectId,
ref: 'profile',
required: true,
}],
User: [{
type: Schema.Types.ObjectId,
ref: 'user',
required: true,
}]
});
const Userpost = mongoose.model('userpost', UserpostSchema);
module.exports = Userpost;
How I populate User and Profile to the UserPost on API
router.get('/getpost/:id', (req, res) => {
const id = req.params.id;
Userpost.find({_id:id}).populate('User').populate('Profile').exec((err,docs) => {
if(err) throw(err);
res.json(docs);
})
});
How do I fetch the entire post of a user to his timeline?
Kindly help please.
Thanks and regards
This should work for u, In UserPost Schema you have taken array for Profile and User which isn't required, and also instead of Schema use mongoose.Schema every where in model.
User Schema
const mongoose = require('mongoose')
const userSchema = new mongoose.Schema({
username: {
type: String,
required: true
},
roles: {
User: {
type: Number,
default: 2001
},
Mentor: Number,
Admin: Number
},
password: {
type: String,
required: true
},
userID: {
type: String,
required: true
},
refreshToken: String
});
const User = mongoose.model('user', userSchema);
module.exports = User;
Profile Schema
const mongoose = require("mongoose");
const ProfileSchema = new mongoose.Schema({
lastname: {
type: String,
required: true,
},
firstname: {
type: String,
required: true,
},
othernames: {
type: String,
required: true,
},
countries: {
type: String,
required: true,
},
phones: {
type: String,
required: true,
},
User: {
type: mongoose.Schema.Types.ObjectId,
ref: "user",
required: true,
},
});
const Profile = mongoose.model('profile', ProfileSchema);
module.exports = Profile;
UserPost Schema
const mongoose = require("mongoose");
const UserpostSchema = new mongoose.Schema({
post: {
type: String,
required: true,
},
Profile: {
type: mongoose.Schema.Types.ObjectId,
ref: "profile",
required: true,
},
User: {
type: mongoose.Schema.Types.ObjectId,
ref: "user",
required: true,
},
});
const Userpost = mongoose.model("userpost", UserpostSchema);
module.exports = Userpost;

Is it possible to reference a mongoose Schema in another mongoose schema without the ObjectId property

I have the two mongoose schemas where one schema reference the other. For example I have
const loginsSchema = new mongoose.Schema({
displayName:{
type:String,
required:true,
},
serviceId:{
required:true,
type:String,
unique:true
}
})
const logins = mongoose.model('logins',loginsSchema);
module.exports = logins;
const usersSchema = new mongoose.Schema({
userName: {
type: String,
required: true,
},
email: {
type: String,
unique: true,
},
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'logins',
unique: true
}
})
What I would like to do is to create a new schema and reference the userSchema in it but not with the objectid. I would like to use the email property.
For Example
const usersSchema = new mongoose.Schema({
name1: {
type: String,
required: true,
},
name2: {
type: String,
unique: true,
},
emailref: {
/// reference the username schema with the email property instead of the objectId
}
})
How can I do that in mongoose?

Embedding another mongoose schema

I'm trying to embed a model in a mongoose schema. Here's what I have:
const People = {
userId: {
type: mongoose.Schema.Types.objectId,
required: true,
ref: 'User'
},
locationId: {
type: mongoose.Schema.Types.objectId,
required: true,
ref: 'Location'
},
};
const Person = mongoose.model(
'Person',
new mongoose.Schema({
...People,
gender: {
type: String
}
})
);
const shmanian = await new Person({gender: 'other', userId:'someUserId', locationId: 'someLocationId'}).save();
The response I get is {gender: 'other'}
The problem is that people doesn't get populated when I create Person.
You should embed an array of "Person" inside a model "People". For example,
const Schema = require("mongoose").Schema;
const model = require("mongoose").model;
const Person = new Schema({
userId: {
type: mongoose.Schema.Types.objectId,
required: true,
ref: 'User'
},
locationId: {
type: mongoose.Schema.Types.objectId,
required: true,
ref: 'Location'
},
});
const People = new Schema({
person: [Person]
});
module.exports = model("People", People);
Here, everytime you create a new Person, you can add it to the People model which contains an array of Person objects.
Not a mongoose Problem.
People is undefined when you create the Object Person.
Thus it doesn't get populated.
Try switching both assignments.

mongoose fetch posts by user and by his followings

How to fetch posts by user and all his followings posts (Mongodb, Mongoose, Nodejs)
User Schema
const userSchema = new mongoose.Schema({
firstName: { type: String, required: true, trim: true },
lastName: { type: String, required: true, trim: true },
});
userSchema.set('timestamps', true);
export default mongoose.model('user', userSchema);
Followers Schema
const followSchema = new mongoose.Schema({
follower: { type: mongoose.Schema.Types.ObjectId, ref: 'user' },
following: { type: mongoose.Schema.Types.ObjectId, ref: 'user' },
status: { type: Boolean, default: true }
});
followSchema.set('timestamps', true);
export default mongoose.model('follow', followSchema);
Posts Schema
const postSchema = new mongoose.Schema({
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'user' },
contents: { type: String, trim: true },
photo: { type: String }
});
postSchema.set('timestamps', true);
export default mongoose.model('post', postSchema);
Thank you in advance! :)
Hy Alamghir its happy to see you here and sorry that you still did not get the answer what i can suggest you after seeing your schema that i think there is no need to create three collections you only need 2 schema first one
const userSchema = new mongoose.Schema({
firstName: { type: String, required: true, trim: true },
lastName: { type: String, required: true, trim: true },
followers:[]
});
userSchema.set('timestamps', true);
export default mongoose.model('user', userSchema);
Now in followers array just push the ids of users who followed this user Now it would be very easy for you to get posts done by these people like this let suppose you have user data in userData variable now you can do this
db.postSchema.find($or:[{userId:userData._id},{userId:$in:userData.followers}])
Sorry, got your question wrong.
There might be a better solution but what you should be able to do is this:
(this gets the posts of the people that are following your original user. If you did mean it the other way around, just switch :) )
// get the user's posts:
var theUserPosts = await postSchema.find({userId: userData._id}).exec();
// get the follower-IDs:
var theFollowersIDs = await followSchema.find({follower: userData._id, status: true}, 'following').exec();
// get the posts of those followers:
var followerPosts = await postSchema.find({userId: {$in: theFollowersIDs}}).exec();
Can you try this and tell us if this works for you?

Resources