I'm working on my personal project which is just simple blog and I got stuck with this problem:
I have 3 Mongoose Schemas:
Blog:
var blogSchema = new mongoose.Schema({
title: String,
image: String,
description: String,
body: String,
created: { type: Date, default: Date.now() },
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Comment"
}
]
});
Comment:
var commentSchema = new mongoose.Schema({
text: String,
author_id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
}
});
User:
var userSchema = new mongoose.Schema({
username: String,
password: String,
avatar_url: String,
email: String
});
And in each blog post I'm trying to display comments from array which is working correctly but then I don't know how to access to User model to display usernames and avatar_urls
app.get("/blogs/:id",function(req,res){
Blog.findById(req.params.id).populate("comments").populate("author_id").exec(function(err,findBlog){
if(err){
res.redirect("back");
console.log(err);
}else{
res.render("show" , {blog: findBlog});
}
})
})
you have to declare user information like username in the blog schema then only you can send request to userschema for avatar_url
Related
I have followed the mongoose docs for populating related objects, everytime authSessions is empty. I can see in mongo sessions are being populated along with the related userId field. I have tried specifying ”path” and “model” options in the populate function as well but that didn’t work either. Anyone have any ideas?
//Session.js
const SessionSchema = new mongoose.Schema({
_id: Schema.Types.ObjectId,
sessionId: { type: String, index: true },
createdDate: { type: Date, default: Date.now },
revoked: Boolean,
revokedAt: Date,
userId: {type: Schema.Types.ObjectId, ref: 'User', index: true}
})
module.exports = mongoose.models.Session || mongoose.model('Session', SessionSchema);
//User.js
const UserSchema = new mongoose.Schema({
_id: Schema.Types.ObjectId,
username: { type: String, index: true },
email: { type: String, index: true },
password: String,
registrationDate: { type: Date, default: Date.now },
authSessions: [{type: Schema.Types.ObjectId, ref: 'Session'}]
})
module.exports = mongoose.models.User || mongoose.model('User', UserSchema);
const user = await User.findById(session.userId).populate('authSessions').exec();
console.log(user) //authSessions is empty
{
_id: new ObjectId("62b6ea393e042868caa68c7d"),
username: 'asdfasdfasdf',
email: 'testaskldjflk#djlkajdf.com',
password: 'testaskldjflk#djlkajdf.com',
authSessions: [], //empty here always
registrationDate: 2022-06-25T10:58:01.709Z,
__v: 0
} ```
MongoDB, and by extension mongoose, doesn't automatically create relations for you.
If you create a Session document, you need to explicitly add it to a User document if you want populate to work:
// create a new session document and save it
const userSession = new Session(…);
await userSession.save();
// !! update the user document and save it
user.authSessions.push(userSession);
await user.save();
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?
So I am currently extremely confused when it comes to mongoose populating.
My data structure is as follows: User has an array of Clients, a Client has an array of loans. I am using User.find and populating the client, no problem. But then how do I populate the loans that is inside of the client? I have tried this:
Basically, the goal is to pass in an array of Clients, each client will contain a loan. But for now, I want that loan object to be empty. The Client is being populated correctly, however, the Loan reference is being passed as undefined.
app.get("/loans", IsLoggedIn, function(req, res) {
User.findById(req.user._id).populate({path: "clients", populate: { path: "loans", model: "loan"}}).exec(function(err, user){
if(err){
console.log(err);
} else{
var amountRepaid = calcRepaid(user.clients.loans);
console.log(user.clients.loans);
res.render("index", {clients: user.clients, amountRepaid: amountRepaid});
}
});
However it doesn't seem to work, my models are listed below and any help is appreciated!
models:
Client:
var mongoose = require("mongoose");
var clientSchema = mongoose.Schema({
loans: [{
type: mongoose.Schema.Types.ObjectId,
ref: "loan"
}],
emailAdderess: String,
firstname: String,
lastname: String,
contactNumber: String ,
dateCreated: {type: Date, default: Date.now},
gender: String,
})
module.exports = mongoose.model("Client", clientSchema);
User:
const mongoose = require("mongoose");
const passportLocalMongoose = require("passport-local-mongoose");
var UserSchema = mongoose.Schema({
username: String,
password: String,
firstname: String,
lastname: String,
clients: [{
type: mongoose.Schema.Types.ObjectId,
ref: "Client"
}]
});
UserSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User", UserSchema);
Loan:
var mongoose = require("mongoose");
var LoanSchema = mongoose.Schema({
firstName: String,
lastName: String,
email: String,
contactNumber: Number,
amountBorrowed: Number,
length: String,
address: String,
dateDue: Date,
gender: String,
date: { type: Date, default: Date.now },
amountRepaid: { type: Number, default: 0},
loanRepaid: {type: Boolean, default: false}
})
module.exports = mongoose.model("loan", LoanSchema);
Try this:
.populate({
path: 'clients',
populate: {
path: 'clients.loans'
}
})
I am learning Mongoose, and got struct on pushing data into array blogs.
my schema is
module.exports = function(mongoose) {
var UserSchema = new Schema({
count:String,
_id : {id:false},
blogs: [{ type: Schema.Types.ObjectId, ref: 'Blog' }]
},
{
timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' }
});
var BlogSchema = new Schema({
blogs:[{
post : String,
title: String,
author : String,
userId: {
type: String,
default: function() {
return crypto.randomBytes(12).toString('hex');
}
},
_id: {type: String, required: true}
}],
});
var models = {
User : mongoose.model('User', UserSchema),
Blog : mongoose.model('Blog', BlogSchema)
};
return models;
}
Problem is here userSchema will always have/be a single object, whcih will keep track of count of total blogs.
I know it can be done using findOneAndUpdate but I don't have id/object created for UserSchema.
Any help is appreciated. Thanks
I wanted to make a base 'Entity Schema', and other model entities would inherit from it.
I did it, kinda, but then strange thing happened.
Those are my schemas:
AbstractEntitySchema
MessageSchema
UserSchema
RoomSchema
File: https://github.com/mihaelamj/nodechat/blob/master/models/db/mongo/schemas.js
But in MongoDB, they are all saved in the same document store: 'entity models' not separate ones, like Messages, Users..
Did I get what was supposed to happen, but not what I wanted, separate stores?
If so I will just make a basic JSON/object as entity and append the appropriate properties for each entity. Or is there a better way?
Thanks.
Discriminators are a schema inheritance mechanism. They enable you to have multiple models with overlapping schemas on top of the same underlying MongoDB collection. rather than different documents. It seems that you misunderstand the discriminators of mongoose. Here is one article could help you to catch it correctly.
Guide to mongoose discriminators
Here are some codes sample to meet your requirement, to save the derived schema as separated documents
function AbstractEntitySchema() {
//call super
Schema.apply(this, arguments);
//add
this.add({
entityName: {type: String, required: false},
timestamp: {type: Date, default: Date.now},
index: {type: Number, required: false},
objectID: {type: String},
id: {type: String}
});
};
util.inherits(AbstractEntitySchema, Schema);
//Message Schema
var MessageSchema = new AbstractEntitySchema();
MessageSchema.add({
text: {type: String, required: true},
author: {type: String, required: true},
type: {type: String, required: false}
});
//Room Schema
var RoomSchema = new AbstractEntitySchema();
RoomSchema.add({
name: {type: String, required: true},
author: {type: String, required: false},
messages : [MessageSchema],
});
var Message = mongoose.model('Message', MessageSchema);
var Room = mongoose.model('Room', RoomSchema);
// save data to Message and Room
var aMessage = new Message({
entityName: 'message',
text: 'Hello',
author: 'mmj',
type: 'article'
});
var aRoom = new Room({
entityName: 'room',
name: 'Room1',
author: 'mmj',
type: 'article'
});
aRoom.save(function(err, myRoom) {
if (err)
console.log(err);
else
console.log("room is saved");
});
aMessage.save(function(err) {
if (err)
console.log(err);
else
console.log('user is saved');
});
If you want multiple overlapping models with different MongoDB collections, then you use this approach:
function extendSchema (Schema, definition, options) {
return new mongoose.Schema(
Object.assign({}, Schema.obj, definition),
options
);
}
Example
const extendSchema = require('mongoose-extend-schema');
const UserSchema = new mongoose.Schema({
firstname: {type: String},
lastname: {type: String}
});
const ClientSchema = extendSchema(UserSchema, {
phone: {type: String, required: true}
});
You simply extend the original object the schema was created with and recreate a new schema on its basis. This is some sort of abstract schema which you inherit from.
Check this npm module: https://www.npmjs.com/package/mongoose-extend-schema
Since ES6 this works as well:
var ImageSchema: Schema = new Schema({
...CommonMetadataSchema.obj,
src: String,
description: String,
});