mongoose schema , Invalid schema configuration - node.js

i have a schema of user that contain an array of movie
i create a new schema of Movie
but i get error of invalid schema configuration.
what i'm doning worng?
enter code here
const mongoose = require("mongoose");
const Movie = require("./movie-model");
const Schema = mongoose.Schema;
const User = new Schema({
firstName: { type: String, required: true },
lastName: { type: String, required: true },
email: { type: String, required: true },
password: { type: String, required: true },
movies: { type: Movie },
});
module.exports = mongoose.model("user", User);
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var Movie = new Schema(
{
name: { type: String, required: true },
time: { type: String, required: true },
rating: { type: Number, required: false },
priorety: { type: Number, required: true },
},
);
module.exports = mongoose.model("movie", Movie);

in movie-model
module.export = Movie
instead of
module.exports = mongoose.model("movie", Movie);

User has many movies
const mongoose = require("mongoose");
const Movie = require("./movie-model");
const Schema = mongoose.Schema;
const User = new Schema({
firstName: { type: String, required: true },
lastName: { type: String, required: true },
email: { type: String, required: true },
password: { type: String, required: true },
movies: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "movie",
},
],
});
module.exports = mongoose.model("user", User);
I invite you to read more about One-to-Many Relationships with Embedded Documents

You need to done referencing in User collection
movies: [
type: mongoose.Schema.ObjectId,
ref: 'user'
]
//instead of doing that
movies: { type: Movie },

Related

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;

Mongoose model how to have an array as property which contains same model as parent

So what I'm trying to do is I want to create a Note object inside note I have a subnote property, I want to have the subnote to be able to be as the same type as the parent model, Right now I'm achieving this by creating two same models with different names and both of them referencing each other for e.x this is the way I'm doing it:
Note schema:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const noteSchema = new Schema({
icon: {
type: String,
},
banner: {
type: String,
},
name: {
type: String,
required: true,
},
user_id: {
type: String,
required: true,
},
date: {
type: Date,
required: true,
default: Date.now,
},
sub_note: {
type: mongoose.Schema.Types.ObjectId,
ref: "sub_notes",
},
content: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "blocks",
},
],
});
module.exports = Note = mongoose.model("notes", noteSchema);
SubNote schema:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const subNoteSchema = new Schema({
icon: {
type: String,
},
banner: {
type: String,
},
name: {
type: String,
required: true,
},
user_id: {
type: String,
required: true,
},
date: {
type: Date,
required: true,
default: Date.now,
},
sub_note: {
type: mongoose.Schema.Types.ObjectId,
ref: "notes",
},
content: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "blocks",
},
],
});
module.exports = SubNote = mongoose.model("sub_notes", subNoteSchema);
But I'm not sure if the above method is the proper way to do it..., Please guide me. Thanks.
u can achieve this by simply doing this
const noteSchema = new Schema({
sub_note: {
type: mongoose.Schema.Types.ObjectId,
ref: "notes",
},
});
module.exports = Note = mongoose.model("notes", noteSchema);
or simply using "this" keyword
const noteSchema = new Schema({
sub_note: this
});
module.exports = Note = mongoose.model("notes", noteSchema);

Mongoose(mongoDB) Linking multiple schema's

Im relatively new to MongoDB and Mongoose. Im much used to MySQL so in used to inner joining tables on calls. Ive read a lot that you can link two Mongoose Schemas to achieve the same outcome. How would like like the two schemas together to when I make a call to get a chore by id it'll return the chore and then for the assignedTo & createdBy have the user scheme data for the said userId?
Chore Schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ChoreSchema = new Schema({
title: {
type: String,
required: true
},
desc: {
type: String,
required: true
},
time: {
type: Number,
required: true
},
reaccurance: {
type: [{
type: String,
enum: ['Daily', 'Weekly', 'Bi-Weekly', 'Monthly']
}]
},
reward: {
type: Number,
required: true
},
retryDeduction: {
type: Number,
required: false
},
createdDate: {
type: Date,
default: Date.now
},
createdBy: {
type: String,
required: true
},
dueDate: {
type: Date,
required: true
},
status: {
type: [{
type: String,
enum: ['new', 'pending', 'rejected', 'completed', 'pastDue']
}],
default: ['new']
},
retryCount: {
type: Number,
default: 0,
required: false
},
rejectedReason: {
type: String,
required: false
},
familyId: {
type: String,
required: true
},
assignedTo: {
type: String,
required: false,
default: ""
}
});
let Chores = module.exports = mongoose.model('Chores', ChoreSchema);
module.exports.get = function (callback, limit) {
Chores.find(callback).limit(limit);
};
User Schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
},
role: {
type: [{
type: String,
enum: ['Adult', 'Child']
}]
},
birthday: {
type: String,
required: false
},
familyId: {
type: String,
required: true
},
balance: {
type: Number,
required: true,
default: 0.00
}
});
let Users = module.exports = mongoose.model('Users', UserSchema);
module.exports.get = function (callback, limit) {
Users.find(callback).limit(limit);
};
Im trying to link ChoreSchema.createdBy & ChoreScheme.assignedTo by UserSchema._id
How I make the call in Node.js:
exports.index = function(req, res) {
Chore.get(function(err, chore) {
if (err)
res.send(err);
res.json({
message: 'Chore List',
data: chore
});
});
};
Mongoose has a more powerful alternative called populate(),
which lets you reference documents in other collections.
https://mongoosejs.com/docs/populate.html
Here is how you can link ChoreSchema.createdBy and ChoreScheme.assignedTo by UserSchema._id
var mongoose = require('mongoose');
const { Schema, Types } = mongoose;
var UserSchema = new Schema({
firstName: { type: String, required: true },
...
})
var ChoreSchema = new Schema({
title: { type: String, required: true },
...
//The ref option is what tells Mongoose which model to use during population
assignedTo: { type: Types.ObjectId, ref: 'Users' },
createdBy: { type: Types.ObjectId, ref: 'Users' },
})
let Chores = mongoose.model('Chores', ChoreSchema);
let Users = mongoose.model('Users', UserSchema);
Then in your express route handler you can populate assignedTo & createdBy like this
router.get('/chores/:id', function (req, res) {
const choreId = req.params.id;
Chores.find({ _id: choreId })
.populate('createdBy') // populate createdBy
.populate('assignedTo') // populate assignedTo
.exec(function (err, chore) {
if(err) {
return res.send(err)
}
res.json({ message: 'Chore List', data: chore });
});
})

mongoose.populate() returning an empty array

I know, this is one of the popular questions out there. On populate I expect it to return the user with his posts, but it's returning an empty array of posts.
Here is my User model.
User.js
const mongoose = require("mongoose")
const Schema = mongoose.Schema
const userSchema = new Schema({
username: { type: String, required: true },
email: { type: String, required: true },
password: { type: String, required: true },
posts: [{
type: mongoose.Schema.Types.ObjectId,
ref: "Post"
}]
}, { timestamps: true })
const User = mongoose.model("User", userSchema)
module.exports = User
Post.js
const mongoose = require("mongoose")
const Schema = mongoose.Schema
const postSchema = new Schema({
postTitle: { type: String, required: true },
postDescription: { type: String, required: true },
user: { type: Schema.Types.ObjectId, ref: "User" },
}, { timestamps: true }
)
const Post = mongoose.model("Post", postSchema)
module.exports = Post
router.get("/posts/:id", usersController.getUserPosts)
usersController.js
getUserPosts: (req, res) => {
User.findById(req.params.id).populate("posts").exec((err, posts) => {
if (err) console.log(err)
console.log(posts)
})
}
I'm getting this:
{ posts: [],
_id: 5e4e3e7eecd9a53c185117d4,
username: 'rick',
email: 'rick#gmail.com',
createdAt: 2020-02-20T08:08:30.878Z,
updatedAt: 2020-02-20T08:08:30.878Z,
__v: 0 }
Where am I going wrong?

Query multiple collections Nodejs

Hello im trying to join these collections i want to get all users which has "active" attribute equal to false. I couldn't figure out how to acquire this query. There are my schemas:
User Schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
type: {
type: String,
required: true
},
active:{
type:Boolean
}
});
module.exports = mongoose.model('users', UserSchema);
Company Schema:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const CompanySchema = new Schema({
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'users'
},
companies: [{
name: {
type:String
},
country:{
type:String
}
}
]
});
module.exports = Company = mongoose.model('company', CompanySchema);
Note: Not all users have companies only the type "client" and i want to get both, "client" and "employe"
You may want to refactor your Schema to better accommodate the type of data you have available.
For example:
User Schema:
const UserSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
type: {
type: String,
required: true
},
active:{
type:Boolean
},
companies: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'company'
}]
});
And Company Schema:
const CompanySchema = new Schema({
name: {
type:String
},
country:{
type:String
}
});
Then to get a list of all users who are active, and automatically populate any company data for those users (Assuming your user model is called UserModel)
UserModel.find({ active: false }).populate('companies').exec();
If you are unable to edit your data structure for any reason, then you could perform a query similar to:
CompanyModel.aggregate([
{ $lookup: { from: 'users', localField: 'userId', foreignField: '_id', as: 'user' } },
{ $match: { '$user.active': false } }
]).exec()
This will perform an aggregate lookup on the UserId field and then only match on ones where the active property is set to false.

Resources