I write 2 models in mongoose. first for Users another for Movies. I wrote this models below. first I save my all user in users collection. after that I want to save my movies to movies collection. but when I want to define my director field I get an error that "ReferenceError: director is not defined"
const userSchema = new Schema({
imdbId: String,
name: String,
});
var User = mongoose.model('user', userSchema);
const movieSchema = new Schema({
imdbId: String,
title: String,
rank: Number,
year: Number,
stars:[{
type: Schema.Types.ObjectId,
ref: 'userSchema'
}],
director:{
type: Schema.Types.ObjectId,
ref: 'userSchema'
}
});
var Movie = mongoose.model('movie', movieSchema);
module.exports = {Movie, User}
and this is my function:
async function findObjectIdByImdbId(str) {
const result = await User.findOne({ imdbId: str})
return result._id
}
async function insertMovieToDb (obj) {
var movie = new Movie ({
imdbId: obj.id,
title: obj.name,
rank: obj.rank,
rating: obj.rating,
year: obj.year,
director: await findObjectIdByImdbId(obj.director)
})
await movie.save(function(err) {
if (err) {console.log(err)
return
}})
}
insertJsonFileToDb().catch(console.log)
Move the await findObjectIdByImdbId(obj.director) out of Movie initialization
E.g.
var directorObjId = await findObjectIdByImdbId(obj.director);
var movie = new Movie ({
imdbId: obj.id,
title: obj.name,
rank: obj.rank,
rating: obj.rating,
year: obj.year,
director: directorObjId
})
Related
I have three schemas:
const journalSchema = new mongoose.Schema({
title: String,
category: String,
subcategory: String,
review: [{type: mongoose.Schema.Types.ObjectId, ref: 'Review'}],
link: String,
description: String,
subscribers: Number,
posts: Number,
image: {
data: Buffer,
contentType: String},
date: Date
});
const userSchema = new mongoose.Schema ({
username: String,
nickname: String,
password: String,
journal: [{type: mongoose.Schema.Types.ObjectId, ref: 'Journal'}],
googleId: String,
age: {type: Date},
gender: {type: String, enum: ["male", "female"]},
admin: Boolean,
role: String
});
const reviewSchema = new mongoose.Schema({
author: {type: mongoose.Schema.Types.String, ref: 'User'},
content: String,
date: Date,
rating: {type: Number, min: 1.0, max: 5.0}
});
const Journal = mongoose.model("Journal", journalSchema);
const User = mongoose.model("User", userSchema);
const Review = mongoose.model("Review", reviewSchema);
Right now any user can leave any number of reviews on the same journal. I want to make it so that a user can leave only one review per journal.
Post route for getting reviews:
app.post("/stats/review", function(req, res){
if(req.isAuthenticated()){
const userNickname = req.user.nickname;
const userId = req.user.id;
const userReview = req.body.journalReview;
const userRating = req.body.rating;
const journalId = req.body.journalId;
Journal.findById({_id: journalId}, function(err, journal){
Review.find({_id: {$in: journal.review}}, function(err, foundReview){
foundReview.forEach(function(review){
if(review.author == userNickname){
console.log("Review from this user already exists");
}
else{
var date = new Date();
const review = new Review();
review.author = userNickname;
review.content = userReview;
review.rating = userRating;
review.date = date;
review.save()
.then((result) =>{
Journal.findOneAndUpdate(
{_id: journalId},
{$push: {
review: review
}},
{useFindAndModify: false},
function(err, success){
if(err){
console.log(err);
}
else{
res.redirect("back");
}
}
);
})
.catch((error) =>{
console.log(error);
})
}
});
})
})
}
else{
res.redirect("/login");
}
});
Is it possible to achieve this with the use of addToSet mongoose method? Couldn't find a fitting solution from similar problems.
I think you need to do some checks here
if the _id already exists in the review field just return some err msg
I'm developing a web app that uses mongodb database using mongoose in node.js...
Now, I'm trying to build the rate feature, in this feature, people can rate the store and give some comments about that store.
This is the structure:
rate: {
author: req.body.author,
text: req.body.text
}
To update it I'm using the "findOneAndUpdate" function, but, Always when i do it, the existent rate is overwritten by the new... Can you guys help me?
Here you can do. I am just demonstrating with example
Model
//Model
const ratingSchema = new mongoose.Schema({
author: { type: String, required: true },
text: { type: String, required: true }
});
const productSchema = new mongoose.Schema({
name: { type: String, required: true },
description: { type: String },
rating: [ratingSchema],
price: { type: Number, default: 1 },
});
module.exports = mongoose.model('Product', productSchema );
Now you can just push a new array
Controller
const ProductModel = require('./models/product');
const { id } = req.params;
const { author, text } = req.body;
PersonModel.update(
{ _id: id },
{ $push: { rating: { author, text }} },
done
);
More about: https://mongoosejs.com/docs/api/array.html#mongoosearray_MongooseArray-push
Try this one
The model
const schema = new mongoose.Schema({
name: String,
description: String,
price: Number,
rating: [{
author : String,
text : String
}]
});
module.exports = mongoose.model('Product', schema );
In request handler
const Product = require('./models/product');
const { id } = req.params; //product ID
const { author, text } = req.body;
const product = Product.findById(id);
product.rating = [...product.rating,{ author, text }]
product.save();
One way is with regular JS, you can simply store the document you want to update in a variable. Then, use the push method on the rate field before calling save on the variable.
I'm doing some tests with MongoDB and NodeJS for a new project.
Searching the documentation I found that it is possible to make references to other collections and bring this data to JSON.
It was then that I decided to perform the following test:
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const userSchema = new Schema({
name: {
type: String,
required: true,
unique: true
},
email: {
type: String,
required: true,
unique: true,
},
posts: [{
type: Schema.Types.ObjectId,
ref: 'Post'
}]
})
const userModel = mongoose.model('User', userSchema)
const postSchema = new Schema({
title: {
type: String
},
content: {
type: String
},
author: {
type: Schema.Types.ObjectId,
ref: 'User'
}
})
const postModel = mongoose.model('Post', postSchema)
const saveUser = new userModel({
name: 'user',
email: 'user#email.com'
})
saveUser.save()
const savePost = new postModel({
title: 'Lorem',
content: 'Lorem Ipsum',
author: saveUser._id
})
savePost.save()
postModel.find()
.populate('User')
.exec((err, post) => {
console.log(post)
})
However the return of JSON is:
{
_id: 5edd0c24a4f42b0e126f4b15,
title: 'Lorem',
content: 'Lorem Ipsum',
author: 5edd0c24a4f42b0e126f4b14,
__v: 0
}
When should it be:
{
_id: 5edd0c24a4f42b0e126f4b15,
title: 'Lorem',
content: 'Lorem Ipsum',
author: {
_id: 5edd0c24a4f42b0e126f4b14,
name: user,
email: user#email.com
},
__v: 0
}
Does anyone know any solution to this problem where I can insert for all my new Schemas?
Regarding populate you should provide the field name provided in postSchema. So should replace .populate('User') with .populate('author').
Since the post requires the author _id you should save the post only after the author is successfully saved
const saveUser = new userModel({
name: "user",
email: "user#email.com",
});
saveUser.save((err, data) => {
if (err) console.log(err);
else {
const savePost = new postModel({
title: "Lorem",
content: "Lorem Ipsum",
author: saveUser._id,
});
savePost.save();
}
});
I´m creating a sport site where Users can create Teams. I want the new Team created to be automatically pushed into the Users membership and leadership arrays. But I can't figure out how to request the newly created Team as shown in the code below:
const Team = require('../models/Team.js')
const path = require('path')
module.exports = async (req,res)=>{
await Team.create({
... req.body,
teamName: req.body.teamname ,
sportType: req.body.sporttype,
description: req.body.description,
location: req.body.location,
members: [req.session.userId],
leaders: [req.session.userId]
});
const user = await req.session.userId;
const teams = //Request newly created Team
await user.leadership.push(teams)
await user.membership.push(teams)
await user.save()
res.redirect('/')
}
Here is the Schema for User:
const UserSchema = new Schema({
username: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
membership: [{ type: Schema.Types.ObjectId, ref: 'Team' }],
leadership: [{type: Schema.Types.ObjectId, ref: 'Team'}]
});
Here is the Schema for Team:
const TeamSchema = new Schema({
teamName: String,
sportType: String,
description: String,
location: String,
members: [{ type: Schema.Types.ObjectId, ref: 'User' }],
leaders: [{type: Schema.Types.ObjectId, ref: 'User'}]
})
module.exports = async (req,res)=>{
const user = User.findById(req.session.userId)
const teams = await Team.create({
... req.body,
teamName: req.body.teamname ,
sportType: req.body.sporttype,
description: req.body.description,
location: req.body.location,
members: [req.session.userId],
leaders: [req.session.userId]
});
await user.leadership.push(teams)
await user.membership.push(teams)
await user.save()
res.redirect('/')
}
Try this. Also, the better approach will be to create different functions for creating the object and then calling it here.
I have a simple relation between topics and categories when topic belongs to a category.
So schema looks like this:
const CategorySchema = new mongoose.Schema({
name: String,
slug: String,
description: String
});
And topic
const TopicSchema = new mongoose.Schema({
category: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Category'
},
title: String,
slug: String,
body: String,
created: {type: Date, default: Date.now}
});
I want to implement particular embedding of category into topic
{
category: {
_id: ObjectId('abc'),
slug: 'catslug'
},
title: "Title",
slug: "topictitle",
...
}
It will help me avoid unnecessary population and obtain performance bonuses.
I don't want to embed whole document because I want to changes categories sometimes (it is a rare operation) and maintain references.
Hope this helps, done it in my own project to save some RTTs in common use cases. Make sure you're taking care of both copies on update.
parent.model.js:
const mongoose = require('mongoose');
const childEmbeddedSchema = new mongoose.Schema({
_id: {type: mongoose.Schema.Types.ObjectId, ref: 'Child', auto: false, required: true, index: true},
someFieldIWantEmbedded: {type: String}
});
const parentSchema = new mongoose.Schema({
child: { type: childEmbeddedSchema },
moreChildren: { type: [{type: childEmbeddedSchema }] }
});
module.exports = mongoose.model('Parent', parentSchema);
child.model.js:
const mongoose = require('mongoose');
const childSchema = new mongoose.Schema({
someFieldIWantEmbedded: {type: String},
someFieldIDontWantEmbedded: {type: Number},
anotherFieldIDontWantEmbedded: {type: Date}
});
module.exports = mongoose.model('Child', childSchema);
parent.controller.js:
const mongoose = require('mongoose');
const Parent = require('path/to/parent.model');
exports.getAll = (req, res, next) => {
const query = Parent.find();
// only populate if requested! if true, will replace entire sub-document with fetched one.
if (req.headers.populate === 'true') {
query.populate({
path: 'child._id',
select: `someFieldIWantEmbedded ${req.headers.select}`
});
query.populate({
path: 'moreChildren._id',
select: `someFieldIWantEmbedded ${req.headers.select}`
});
}
query.exec((err, results) => {
if (err) {
next(err);
} else {
res.status(200).json(results);
}
});
};