How to make reference beetween two schema mognose node.js - node.js

I try to make refrence in my MERN app beetwen two schema Movie and Seanse.
This is my Movie Schema:
const Movie = mongoose.Schema({
title: {
type: String,
require: true,
},
movieDescription: {
type: String,
require: true,
},
movieImgUrl: {
type: String,
require: true,
},
seanses: [
{
type: Schema.Types.ObjectId,
ref: "Seanse",
},
],
});
export default mongoose.model("Movie", Movie);
And this is my Seanse schema:
const Seanse = mongoose.Schema({
date: {
type: Date,
require: true,
},
hour: {
type: String,
require: true,
},
movie: {
type: Schema.Types.ObjectId,
ref: "Movie",
},
bookings: {
type: Array,
require: true,
},
});
export default mongoose.model("Seanse", Seanse);
But when i requests for movies in postman I see empty array, this is my code for geting all movies :
async findAll(req, res) {
const movies = await Movie.find().populate({
path: "seanses",
model: "Seanse",
});
return res.status(200).send({ data: movies });
},
This is what I recive at Postman :
{
"seanses": [],
"_id": "5f5bea1993df462974d63e66",
"title": "Hacker 5",
"movieDescription": "Lorem Ipusm",
"movieImgUrl": "https://m.media-amazon.com/images/M/MV5BZGJiZGMwMmUtMjdiZS00M2QzLWE3YjAtNTU2MjQ2ZDE3NDE1XkEyXkFqcGdeQXVyMTc5OTQwMzk#._V1_.jpg",
"__v": 0
}
Of course, I have previously created seanse in which I entered the id of an existing movie in the "movie" field

Mongoose always adds 's' to the end of model name, so you should rename Movie to Movies and Seanse to Seanses.

Related

Updating array of objects inside an object mongodb node

I have a mongoDb model defined as follows:-
var mongoose = require("mongoose");
const postModel = new mongoose.Schema({
postId: {
type: String,
unique: true,
required: true
},
authorId: {
type: String,
required: true
},
post: {
authorHandle: {
type: String,
required: true
},
heading: {
type: String,
required: true
},
message: {
type: String,
required: true
},
creationDate: {
type: Date,
required: true
},
image: { type: Array },
video: { type: Array },
comments: {
type: Array
}
}
});
module.exports = mongoose.model("postModel", postModel);
Now I have a sample value of a document of the above model, suppose:-
postId: "aaa",
authorId: "bbb",
post: {
authorHandle: "someone#123",
heading: "hello",
message: "post 1",
creationDate: "some creation date string(please ignore this is irrelevant to my question)",
image: [],
video: [],
comments: [
{ commentId: "1", message: "Something", createdAt: sometime },
{ commentId: "2", message: "Something else", createdAt: sometime2 },
{ commentId: "3", message: "Something other", createdAt: sometime3 },
]
}
Now say the user wants to update the comment with commentId 2 of this post with postId "aaa". My question is that what is the best way to use the findOneAndUpdate() method to solve this problem?
const PostModel = require("./models/PostModel"); //just importing the model that is defined above
//the below is happening inside a request handler in Node + Express
PostModel.findOneAndUpdate(
//what to do here
)
What I have tried is pulling out that whole object and replacing it with a new object with the new message. But that doesnt seem like a very efficient way. Any and all help is greatly appreciated!
You should write:
const updatedPost = await PostModel.findOneAndUpdate(
{ postId: 'aaa', 'post.comments.commentId': 2 },
{ 'post.comments.$.message': 'Updated message'},
{ new: true }
)

What is the best approach to save a 4 level nested schema in mongoose NodeJs

I have 4 level nested schema:
Framework has Domain referenced to it, Domain has control referenced to it, and Control has SubControl referenced to it.
Now I have been searching for a while and I keep getting confused.
First question: is it possible to post all the data from the framework it self?
Second question: I have used referencing with ID approach, should I switch to using subDocuments?
Framework Schema:
const FrameworkSchema = new Schema({
name: {
type: String,
trim: true
},
description: {
type: String,
trim: true
},
domain: [{
domain: {type: Mongoose.Schema.Types.ObjectId, ref: 'Domain'}
}],
updated: Date,
created: {
type: Date,
default: Date.now
}
});
module.exports = Mongoose.model('Framework', FrameworkSchema);
Domain Schema:
const DomainSchema = new Schema({
_id: {
type: Schema.ObjectId,
auto: true
},
domainNo: {
type: String,
trim: true
},
domainName: {
type: String,
trim: true
},
domainDescription: {
type: String,
trim: true
},
framework: {
type: Mongoose.Schema.Types.ObjectId,
ref: 'Framework'
},
control: [{
control: {type: Mongoose.Schema.Types.ObjectId, ref: 'Control'}
}],
updated: Date,
created: {
type: Date,
default: Date.now
}
});
module.exports = Mongoose.model('Domain', DomainSchema);
My control Schema:
const ControlSchema = new Schema({
_id: {
type: Schema.ObjectId,
auto: true
},
mainControl: {
type: String
},
subControl: [{
subControlNo: {type: Mongoose.Schema.Types.String, ref: 'SubControl'}
}],
controlDescription: {
type: String,
trim: true
},
updated: Date,
created: {
type: Date,
default: Date.now
}
});
module.exports = Mongoose.model('Control', ControlSchema);
My SubControl Schema
const SubControlSchema = new Schema({
_id: {
type: Schema.ObjectId,
auto: true
},
subControlNo: {
type: [String]
},
updated: Date,
created: {
type: Date,
default: Date.now
}
});
module.exports = Mongoose.model('SubControl', SubControlSchema);
Now I'm trying to post this nested documents from the framework api:
router.post(
'/add',
auth,
role.checkRole(role.ROLES.Admin), async (req, res) => {
try {
const subControl = new SubControl({...req.body});
const subControlDoc = await subControl.save();
const control = new Control({...req.body}); // take the control data
control.subControl.push(subControlDoc._id); // take the subControl and push the ID into the control
const controlDoc = await control.save();
//make the subcontrol pushed into control
// make control pushed in domain
const domain = new Domain({...req.body});
domain.control.push(controlDoc._id);
const domainDoc = await domain.save();
const framework = new Framework({...req.body});
framework.domain.push(domainDoc._id);
const frameworkDoc = await framework.save(); //save the framework + domain's ID
res.status(200).json({
success: true,
message: `Framework has been added successfully!`,
framework: frameworkDoc
});
} catch (error) {
res.status(400).json({
error
// error: 'Your request could not be processed. Please try again.'
});
}
}
);
Now I'm using push to push the data as an array, not sure if this the right approach, and Is it possible to post the all the data from the framework api?
Tried to post this from postman:
{
"name": "ISO780001",
"description": "frameworkDescription",
"domain":
[
{
"domainNo": "11",
"domainName": "domainName00",
"domainDescription": "domaindescu0",
"control": [{
"mainControl": "1-4",
"subControl": [{
"subControlNo": "1-4-1"
},
{
"subControlNo": "1-4-2"
}],
"controlDescription": "controlDescriptionTest"
},
{
"mainControl": "1-4",
"subControl": [{
"subControlNo": "1-4-1"
},
{
"subControlNo": "1-4-2"
}],
"controlDescription": "controlDescriptionTest"
}
]
},
{
"domainNo": "1-2",
"name": "domainName00",
"description": "domaindescu0",
"control": {
"mainControl": "1-4",
"subControl": [{
"subControlNo": "1-4-1"
},
{
"subControlNo": "1-4-2"
}],
"controlDescription": "controlDescriptionTest"
}
}
]
}
Only the id's of the domain, control, and subControl get saved in mongodb, is this the how it works can I post all the data from one model in this case the framework? or should I use embedded approach ?
What I will do in scenario where i have alot of references (mongoose name it ref by the way, which allows you to populate).
Example of a frameWork schema with domain reference.
const frameworkSchema = mongoose.Schema({
domains: [{type: mongoose.Schema.Types.ObjectId, ref: 'Domain'}],
})
const FrameworkModel = mongoose.model('Framework', frameworkSchema)
Domain above refers to a Domain model. We can create a domain model now.
const domainSchema = mongoose.Schema({
_id: { type: mongoose.Schema.Types.ObjectId } //this is the default
})
const DomainModel = mongoose.model('Domain', domainSchema);
Example Usage - We want to get all the domain information related to a specific schema.
const results = FrameworkModel.findOne({ _id: 'some framework id'}).populate('domains').lean({ virtuals: true });
The results will be something like
{
_id: 'some framework id',
name: 'name of framework',
domains: [
{
_id: 'id of domain 1',
name: 'example.com'
},
{
_id: 'id of domain 2',
name: 'example2.com'
}
]
}
You can also explore virtuals to see how you can maintain your framework, domains and other controls as separate collections, in order to easily reference to them. This is a better design than nesting multiple levels in a single document.
Unless where necessary, using separate collections has more benefits than using subdocuments. (easier to find documents and easier to update documents, and of course, more performant)

Query MongoDB w/Mongoose on an Array of objects

I am having a rough time querying my collection of data, Im building a simple E-Comm platform and in that platform i want to be able to have categories for the products. the idea is simple, each category should be its own object in the database that has a collection of products, however each product can have multiple categories, this is for products that might fit into one or more category definitions.
here is the model for the categories
import mongoose from "mongoose";
const categorySchema = mongoose.Schema(
{
cat_name: {
type: String,
required: true,
unique: true,
},
cat_items: [
{
product: {
type: mongoose.Schema.Types.ObjectId,
ref: "Product",
},
},
],
// Adds a relationship between a User admin and a product
// this is useful to see which admin, if multiple created a category
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "User",
},
},
{ timestamps: true }
);
const Category = mongoose.model("Category", categorySchema);
export default Category;
Here is the Product model
const productSchema = mongoose.Schema(
{
// Adds a relationship between a User admin and a product
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "User",
},
name: {
type: String,
required: true,
},
image: {
type: String,
required: true,
},
brand: {
type: String,
required: true,
},
category: {
type: String,
required: true,
},
categories: [
{
category: {
type: mongoose.Schema.Types.ObjectId,
ref: "Category",
},
},
],
description: {
type: String,
required: true,
},
reviews: [reviewSchema],
rating: {
type: Number,
required: true,
default: 0,
},
numReviews: {
type: Number,
required: true,
default: 0,
},
price: {
type: Number,
required: true,
default: 0,
},
countInStock: {
type: Number,
required: true,
default: 0,
},
},
{
timestamps: true,
}
);
const Product = mongoose.model("Product", productSchema);
export default Product;
I believe the overall problem is the way i have the models setup, because any query i run on the categories object to return the products associated with it in cat_items, does not return any products it simply returns an empty array.
here is the simple function to return data
const products = await category.map((product)=> { return Product.findById(product._id)})
here im pulling out the array of category items, and mapping over them looking for the product in the database by the _id which is what product is example: 620e626203a59f0004e5a8c6 this in theory if you had 3 items, would return a new array of the product objects that i can send to the client, however every attempt only returns a [] and im pretty sure this is all do in part to the way i have the models setup.
for reference this is what returning a category looks like in postman:
{
"category": {
"_id": "62102f5c2b990d0e7c7d9bf8",
"cat_name": "Pendants",
"user": "620af3311fe4c247904b84d9",
"cat_items": [
{
"_id": "620e626203a59f0004e5a8c6"
},
{
"_id": "620e626203a59f0004e5a8c6"
}
],
"createdAt": "2022-02-18T23:44:28.697Z",
"updatedAt": "2022-02-18T23:54:23.103Z",
"__v": 2
},
"products": [
{},
{}
]
}
where im trying to fill the products array with the actual products stashed in the database

POPULATION ISSUE: Mongoose/Express

I'm trying to have each record attached to a user who created it,
and every user have their records attached.
Here are my schemas:
1.The Records schema:
const mongoose = require('mongoose')
const RecordsSchema = new mongoose.Schema(
{
Title: { type: String, required: true },
postedby:[{
type: mongoose.Schema.Types.ObjectId,
ref: 'user'
}],
Author: { type: String, required: true},
ISBN: { type: String, required: true },
Review: { type: String },
SelectedFile: { type: String },
Likes: { type: Number, default:0},
Date: { type: Date, default: Date.now()}
});
module.exports = Records = mongoose.model('record', RecordsSchema', 'record');`
Here is the The user Schema:
const mongoose = require('mongoose')
const userSchema = new mongoose.Schema(
{
username: { type: String},
email: { type: String, required: true ,unique:true},
records:[{
type: [mongoose.Schema.Types.ObjectId],
ref: 'record' }],
password: { type: String, required: true},
Date: { type: Date, default: Date.now(), immutable: true }
});
module.exports = User = mongoose.model('user', userSchema,'user');
The express route for getting a record:
router.get('/postedby/', (req, res) => {
Records.find(req.params.id)
.populate('postedby')
.exec()
.then(post =>{
if (!post) {
return res.status(400).json({ msg: 'Add Posts' });
}
else return res.json(post);
}).catch (err => console.error(err))
});
Result of the route:
{
"postedby": [],
"Likes": 0,
"_id": "5fed8c12a4fb2c1e98ef09f6",
"Title": "New Age",
"Author": "Situma Prisco",
"ISBN": "23422",
"SelectedFile": "",
"Review": "",
"Date": "2020-12-31T08:30:10.321Z",
"__v": 0
},
I'm getting a blank Array on the populated user field(posteddby) .
Please help, What am I doing wrong? And yes, i do have a User Logged in
You are too close.
In your schema definition, postedby field itself is an array. Hence you can simply define it like :
postedby:[{
type: mongoose.Schema.Types.ObjectId,
ref: 'user'
}]
Make sure that the ObjectID is stored properly in the postedby array.
Also, you are trying to find a single record based on the ID, hence you can use findById(req.params.id) or findOne({_id:req.params.id}) which would return a single document.

Populate() Mongoose is not returning joined data

Well, I´am trying to retrieve Name and Lastname from user who created the document but it´s not working, it still returning Mongo´s Id
This is my areas model
var mongo = require('mongoose'),
validator = require('mongoose-unique-validator'),
Schema = mongo.Schema
var model = new Schema({
NAME: { type: String, required: true, unique: true, max: 50, min: 3 },
STATUS: { type: String, default: 'active' },
ADDED_BY: { type: Schema.Types.ObjectId, ref: 'users' },
ADDED_DATE: { type: Date, default: Date.now }
}, {collection :'areas'})
model.plugin( validator, { message: 'The {PATH} is not valid or duplicated' } )
module.exports = mongo.model('Area', model )
This is the user model
var mongo = require('mongoose'),
validator = require('mongoose-unique-validator'),
Schema = mongo.Schema
var userSchema = new Schema({
PERSONAL_DATA: {
NAME: { type: String, required: [ true, 'The name is necessary' ], max: 50 },
LAST_NAME: { type: String, required: [ true, 'the lastname is necessary' ], max: 100 },
PHOTO: { type: String, max: 100 },
BIRTHDAY: { type: Date },
MARITIAL_STATUS: { type: Schema.Types.ObjectId, ref: 'maritial_statuses' },
GENDER: { type: String, max: 1 },
EMAIL: { type: String, required: true },
},
COMPANY_DATA: {
JOB: { type: Schema.Types.ObjectId, ref: 'jobs' },
AREA: { type: Schema.Types.ObjectId, ref: 'areas' },
ROLE: { type: Schema.Types.ObjectId, ref: 'roles' },
BOSS: { type: Schema.Types.ObjectId, ref: 'users' },
}
}, { collection: 'users' } )
model.plugin( validator, { message: 'The {PATH} is not valid or duplicated' } )
module.exports = mongo.model('User', userSchema )
And this is my areas route
var express = require('express'),
model = require('../../models/catalogs/areas'),
app = express()
app.get('/:from', (req, res) => {
var from = parseInt( req.params.from )
model.find()
.sort('NAME').populate({ path: 'users', select: 'NAME LAST_NAME'})
.limit(10).skip(from)
.exec((error, data) => {
if (error) {
return res.status(500).json({
success: false,
error
})
}
res.status(200).json({
success: true,
data
})
})
})
module.exports = app
The response is
{
"success": true,
"data": [
{
"STATUS": "active",
"_id": "5c547f4adadf433914f72c8c",
"NAME": "Contabilidad y Finanzas",
"ADDED_BY": "5c4f562deec6f4defeea759b",
"ADDED_DATE": "2019-02-01T17:18:02.680Z",
"__v": 0
},
{
"STATUS": "active",
"_id": "5c547f3edadf433914f72c8b",
"NAME": "Tecnologías",
"ADDED_BY": "5c4f562deec6f4defeea759b",
"ADDED_DATE": "2019-02-01T17:17:50.579Z",
"__v": 0
}
]
}
As you seen, ADDED_BY is a field joined to Users and I want to retrieve that information. I don´t know what is wrong with my code.

Resources