In a user schema, I need to define a field of contacts with a blocked property.
My actual definition goes like this:
const UserSchema = new Schema({
id: Schema.Types.ObjectId,
// Other fields
// ...
contacts: [{
type: Schema.Types.ObjectId,
ref: 'User'
}]
}
const UserModel = mongoose.model('User', UserSchema);
From there I was unable to find a possible way to add the blocked field in the same referenced relationship contacts. Is it necessary to create an Intermediary Collection to add the additional field to the relation?
I ended up creating a contact collection which holds at the same time a reference to the user plus the additional fields that I need:
//user.js
const UserSchema = new Schema({
id: Schema.Types.ObjectId,
// Other fields
// ...
contacts: [{
type: Schema.Types.ObjectId,
ref: 'Contact'
}]
}
const UserModel = mongoose.model('User', UserSchema);
//contact.js
const ContactSchema = new Schema({
id: Schema.Types.ObjectId,
contact: {
type: Schema.Types.ObjectId,
ref: 'User'
},
blocked: {
type: Boolean,
required: true
}
}
const ContactModel = mongoose.model('Contact', ContactSchema);
Related
Making an app with a variety of schemas, many having other objects (Schema.Types.ObjectIds) as their properties.
When doing this, I can access the sub-object's property, as long as that sub-object's property is a string. But I'm having issues with it if that sub-object's property is yet another object (and then I need to query properties from that, string or not). For example, the first works fine:
user schema-> friends property of user (which is a list of user objects) -> username property of friend (which is a string)
But this I'm having issues with, I'm getting a string id and not the actual object**:
user schema-> profilePosts property of user (which is a list of profilePost objects) -> author property of profilePost (which is a user object)** -> author username property of profilePost (which is a string)
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var UserSchema = new Schema({
username: {type: String, required: true},
password: {type: String, required: true},
friends: [{type: Schema.Types.ObjectId, ref: "User"}],
profilePosts: [{type: Schema.Types.ObjectId, ref: "ProfilePost"}],
friendRequests: [{type: Schema.Types.ObjectId, ref: "User"}],
})
module.exports = mongoose.model('User', UserSchema);
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var ProfilePostSchema = new Schema({
date: {type: Date, required: true},
author: {type: Schema.Types.ObjectId, ref: "User"},
content: {type: String, required: true},
comments: [{type: Schema.Types.ObjectId, ref: "ProfilePostComment"}],
likes: [{type: Schema.Types.ObjectId, ref: "User"}],
hostProfile: {type: Schema.Types.ObjectId, required: true,ref: "User"},
})
module.exports = mongoose.model('ProfilePost', ProfilePostSchema);
exports.user_friends_render = async (req,res) => {
try {
const ViewedProfile = await User.find({}, 'username friends profilePosts friendRequests').populate('friends').populate('profilePosts').populate('friendRequests');
res.status(200).json(ViewedProfile);
} catch(error) {
res.status(200).json({message: error.message});
}
}
objects are string ids instead of objects
Mongoonse populate root object but not implicit deep populate
You can replace string by object as argument at populate method,
for provide full path to populate
const ViewedProfile = await User
.find({}, 'username friends profilePosts friendRequests')
.populate('friends')
.populate({
path: "profilePosts",
populate: [
{
path: "author",
// model: UserModel
},
{
path: "comments",
// model: ProfilePostCommentModel
},
{
path: "likes",
// model: UserModel
},
{
path: "hostProfile",
// model: UserModel
}
]
})
.populate('friendRequests');
You can see fully post at this problem.
The idea is about one comment contains children comments, it is about a comment contains responses. For that, I create my Comment schema like this:
import mongoose from 'mongoose';
//to connect to our database
import db from '../db/connectDB.js'
const Schema = mongoose.Schema // Define Schema method= mongoose;
const CommentSchema = new Schema({
id_parent : {
type: Number,
required: true,
},
user_name: {
type: String,
},
content: {
type: String,
},
created_date: {
type: Date,
default: Date.now,
},
counter_like: {
type: Number,
required:false,
},
status : {
type: String,
},
});
export default mongoose.model('Comment', CommentSchema);
then my parentComment schema like this:
import mongoose from 'mongoose';
//to connect to our database
import db from '../db/connectDB.js'
const SchemaParent = mongoose.Schema // Define Schema method= mongoose;
const ParentCommentSchema = new Schema({
parent_comment:{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment'
},
children_comments: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment'
}]
});
export default mongoose.model('ParentComment', ParentCommentSchema);
It seems not clean, I don't want to insert the child comment every time I want to insert it directly in the the parent comment, I don't get the idea, any help
You could simply reference the parent ID in the comment itself
const commentSchema = new Schema({
_id,
parentId : { type: mongoose.Schema.Types.ObjectId, ref: 'Comments' },
user: { type: mongoose.Schema.Types.ObjectId, ref 'Users'},
[...]
});
This way you can .find({parentId: commentId}) to find all the comments that would be "answers" of the commentId (parent). You will have an array of Comment
Otherwise you can embed directly the comments inside each others.
const commentSchema = new Schema({
_id,
user: { type: mongoose.Schema.Types.ObjectId, ref 'Users'}
});
commentSchema.add({comments: {type: [commentSchema], default: undefined})
You'd have something like :
comment {
_id: 'qzrqrsrt',
user: '1'
content : "What do you guys think ?"
comments : [
{
_id: 'qzrqzrqzr',
user: '2',
content: 'Ahah nice',
comments: [
{
_id: 'qiorqzpçrq',
user: '1',
content: 'Thanks'
}
]
},
{
_id: 'dryhsertse',
user: '2'
content: "I'll use it"
}
]
}
But that would be a bit more difficult to find the comment you want to add answers to
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.
I have two mongoose schemas 'user' and 'project' and i want to show relationship between these schemas like in mysql. How to do this?
And how can i pass user while creating a project?
User.js
const mongoose = require('mongoose');
const bcrypt = require('bcrypt-nodejs');
const Schema = mongoose.Schema();
const UserSchema = mongoose.Schema({
fullname: {type: String},
username : {type:String},
password: {type:String}
});
UserSchema.methods.encryptPassword = function(password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(10), null);
};
UserSchema.methods.comparePassword = function(userPassword, cb) {
bcrypt.compare(userPassword, this.password, (err, isMatch) => {
if(err) throw err;
cb(null, isMatch);
});
}
module.exports = mongoose.model('User', UserSchema);
project.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema();
const User = require('./user');
const ProjectSchema = mongoose.Schema({
title: {type: String, required: true},
description: {type:String},
created_at: { type: Date, default: Date.now },
publish : { type: Boolean, default: false}
});
module.exports = mongoose.model('Project', ProjectSchema);
Creating schema in Mongoose isn't like creating schema in Relational DBMS, such as MySQL, PostGreSQL.
You can use objectId, bro.
If one project just can be handled by one user, you can use something like this.
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
But if one project is handled by multi users
users: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}]
Hope it will help
Schema Change
To create a relationship in Mongoose (MongoDB), create a property on your schema with the following properties
1. type: mongoose.Schema.Types.ObjectId
2. ref: "string name of the Collection this reference lives in"
For example, if you wanted a project to contain a reference to the users inside of it, you could do the fallowing
const mongoose = require('mongoose');
const Schema = mongoose.Schema();
const User = require('./user');
const ProjectSchema = mongoose.Schema({
title: {type: String, required: true},
description: {type:String},
created_at: { type: Date, default: Date.now },
publish : { type: Boolean, default: false},
users: [{type: Schema.Types.ObjectId, ref: 'User'}]
});
module.exports = mongoose.model('Project', ProjectSchema);
Example Opertaion
Given the above Schema, if you wanted to create a new Project and add users to it during creation, you would need to have those users' _id properties on hand (i.e. cached). That could mean making a prior query to the db to get all the users who will be a part of this project or having some client send you the user ids.
A much better option would be to create a project, and update its' users property as users are added or removed.
Here is a quick example
const Project = require('./models/Project.js');
let userIds = // get the user _ids some how
Project.create({
title: 'A sample',
description: 'The usual',
publish: true,
users: userIds
})
.then(callback);
Users in my database are declared inside a class as follows:
class User {
constructor() {
this.user = mongoose.model('user', {
email: String,
name: String,
})
}
validPassword(collection, password) {
... ...
}
}
const user = new User();
module.exports = user;
In my PostSchema, I want author to point to the above Schema, but I don't know how to write the part after ref:. I tried User, it gave me an error MongooseError: Schema hasn't been registered for model "User".
var PostSchema = new mongoose.Schema({
title: { type: String, default: "DefaultTitle" },
author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
})
Could anyone help?
Turn your ref to 'user' with a downcase.
This notation refers to mongodb dbref
The ref is the collection name wich is in your case (according to the schema declaration) "user" in downcase.
This will be your Post declaration :
var PostSchema = new mongoose.Schema({
title: { type: String, default: "DefaultTitle" },
author: { type: mongoose.Schema.Types.ObjectId, ref: 'user' },
})