Mongoose pre-save hook fires, but does not persist data - node.js

I am encountering a problem where my Mongoose pre.save() hook is firing, but the attribute does not get saved to the database. I have been searching for a long time without finding an answer.I found this thread, and the behaviour I am experiencing is very similiar, but OP's problem is related to the context of this, whereas I seem to have a different problem.
Here is my models.js:
'use strict';
const mongoose = require("mongoose");
const slugify = require("slugify");
let Schema = mongoose.Schema;
let BlogPostSchema = new Schema({
title: {
type: String,
required: true
},
createdAt: {type: Date, default: Date.now},
updatedAt: {type: Date, default: Date.now},
author: String,
post: {
type: String,
required: true
}
});
BlogPostSchema.pre('save', function(next) {
this.slug = slugify(this.title);
console.log(this.slug);
next();
});
// Passed to templates to generate url with slug.
BlogPostSchema.virtual("url").get(function() {
console.log(this.slug);
console.log(this.id);
return this.slug + "/" + this.id;
});
BlogPostSchema.set("toObject", {getters: true});
let BlogPost = mongoose.model("BlogPost", BlogPostSchema);
module.exports.BlogPost = BlogPost;
And here is the relevant lines in the router file index.js:
const express = require('express');
const router = express.Router();
const BlogPost = require("../models").BlogPost;
// Route for accepting new blog post
router.post("/new-blog-post", (req, res, next) => {
let blogPost = new BlogPost(req.body);
blogPost.save((err, blogPost) => {
if(err) return next(err);
res.status(201);
res.json(blogPost);
});
});
I am able to save the blog post to the database, and my console.log's correctly prints out the slug to the console. However, the this.slug in the pre-save hook does not get persisted in the database.
Can anybody see what the problem is here? Thank you so much in advance.

Mongoose will act according to the schema you defined.
Currently, your schema does not contain s filed named slug.
You should add a slug field to your schema.
Changing your current schema to something like this should work:
let BlogPostSchema = new Schema({
slug: String,
title: {
type: String,
required: true
},
createdAt: {type: Date, default: Date.now},
updatedAt: {type: Date, default: Date.now},
author: String,
post: {
type: String,
required: true
}
});

Related

empty result when getting data from mongodb with mongoose and node js

I'm trying to fetch all my documents from a collection in my MongoDb DB but I can't do it. I have absolutely no error but it just returns an empty array in my console.
Model :
import mongoose from "mongoose";
const websiteSchema = mongoose.Schema({
id: {type: String},
name: {type: String, required: true},
url: {type: String, required: true},
note: {type: Number, required: true}
});
export default mongoose.model("Website", websiteSchema);
File in which I want to use the data :
import express from 'express';
import Website from '../models/website.js';
const routerWebsiteList = express.Router();
routerWebsiteList.get('/website-list', async function(req, res, next) {
try {
const websitesToCrawl = await Website.find({});
console.log(websitesToCrawl);
} catch (error) {
res.status(500).json({message : "An error occured"});
}
})
export default routerWebsiteList;
All I get in my console is [].
My data in my database seems good too :
Accully everything looking fine maybe you can use
require for import files
const name = require('name')
and for the export file :
module.exports = routerWebsiteList
after that be sure you connected your database correct like this
async function database() {
await mongoose
.connect(process.env.DATABASE_URL)
.then(() => {
console.log("Database Coonected");
})
.catch((err) => {
console.log(err);
});
}
database()
Last detail is you don't need to put id on mongoose schema just remove it and finally change your model like this
const mongoose = require("mongoose");
const websiteSchema = mongoose.Schema({
name: {type: String, required: true},
url: {type: String, required: true},
note: {type: Number, required: true}
});
const Website = mongoose.model("Website", websiteSchema);
module.exports = Website
I hope that will be helpful. If you will be stuck somewhere feel free to type here again.
I finally found what was the problem. The mongoose Schema was looking in a wrong collection named "websites". All I had to do was to specified the collection name in my model as following : ("websitesToCrawl" is the collection name)
export default mongoose.model("Website", websiteSchema, "websitesToCrawl");

Edited object/document not saving properly on MongoDB in MERN app

I'm building a MERN application where blog posts are created and edited, and comments to blog posts can be added and edited. When a blog post is added or edited everything works as expected, and comments are added as expected as well. But when a comment is edited, it doesn't save properly in the database. It gets saved across the session because of rendering functions I added in the react files, but when the app is reloaded the comment edit is gone and the comment is back to how it was originally. When I look at the database, I notice the edited comment is added by itself, but its original copy inside of the comment is not edited. I'm assuming there is an issue with how I'm configuring the model schemas, and/or I'm not accessing the blog post document directly. But I don't know exactly what the issue is despite what I've tried.
Below are two editComment functions that I've tried in the server side express/mongoose files, the first is successful at adding the edited comment to the database but it's failing to access and edit the original one inside of the blog post. The second one is taking into consideration the object id of the post the comment is in, but this just sends a 500 error and goes nowhere. I also have the blog post and comment schemas provided to give a better idea of where the issue may lie.
try {
let newDate = new Date();
let date = newDate.toDateString();
let post = req.params.postid;
const { title, content } = req.body;
const updatedComment = await Comment.findByIdAndUpdate(req.params.commentid, {title, date, content, post});
await updatedComment.save();
res.status(200).json(updatedComment);
} catch (error) {
res.status(404).json( {message: error.message} );
}
}
try {
const { title, content } = req.body;
let newDate = new Date();
let date = newDate.toDateString();
let post = new mongoose.Types.ObjectId(req.params.postid);
const postDoc = await Post.findById(post).lean().exec();
const comment = await Comment.findById(req.params.commentid).exec();
comment.title = title;
comment.date = date;
comment.content = content;
comment.post = post;
const updatedComment = await comment.save();
res.status(200).json(updatedComment);
} catch (error) {
res.status(500).json( {message: error.message} );
}
}
var PostSchema = new Schema({
title: {type: String, required: true, maxLength: 300},
date: {type: String, required: true},
content: {type: String, required: true},
comments: [{type: Object, required: true}],
})
module.exports = mongoose.model('Post', PostSchema);
var CommentSchema = new Schema({
title: {type: String, required: true, maxLength: 300},
date: {type: String, required: true},
content: {type: String, required: true},
post:{type: Schema.Types.ObjectId, ref:"Post", required: true},
})
module.exports = mongoose.model('Comment', CommentSchema);

Mongoose findByIdAndUpdate

I trying to edit and update a form using mongoose. The code seems fine to me, but it doesn't work. I have tried so many ways but the updated version is still the same, I uses a put route to send the form, when I output req.body.studentInfo to the console, it is correct, but the update remains the same. Please help
This is my schema
var mongoose = require("mongoose");
var uniqueValidator = require('mongoose-unique-validator');
var passportLocalMongoose = require("passport-local-mongoose");
var mongoose = require("mongoose");
var UserSchema = new mongoose.Schema({
studentInfo: {
first_name: String,
middle_name: String,
last_name: String,
street: String,
town: String,
city: String,
region: String,
country: String,
studentId: String,
day: Number,
month: String,
year: Number,
},
username: {type: String, required:true, unique:true},
passport: String
});
UserSchema.plugin(uniqueValidator);
UserSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("StudentInfo", UserSchema);
This is my App.js
app.put('/:id', function(req,res){
StudentInfo.findByIdAndUpdate(req.params.id, {$set: req.body.studentInfo}, function(err, updated){
console.log(req.params.id);
console.log(req.body.studentInfo);
if(err) {
console.log(err);
}
else {
res.redirect('/' + req.params.id);
}
});
});
The studentInfo is an object that contains the names of each variables in my form which I name was studentInfo[name of variable]. Please help
It should be specified that mongoose should return the updated document - by default it returns the original (this is also the behavior of mongodb). I think that if the code gets changed to this:
StudentInfo.findByIdAndUpdate(req.params.id, {$set: req.body.studentInfo}, { new: true }, function(err, updated){
...
});
you will receive the updated document in the callback.
As #Denny mentioned in his answer, mongoose will not return the updated document in the callback until you pass {new : true } option.
For Details and available options check findByIdAndUpdate Docs

While creating api with nodejs, reference error: schema is not defined

I want to reach information with get method on Postman. But whenever i "localhost:3000/api/mekanlar/mekan's objectid", i get reference error "Mekan is not defined". Here is my mekansema.js file in /app_api/models.
var mongoose = require('mongoose');
var saatSema = new mongoose.Schema({
gunler: {type: String, required: true},
acilis: String,
kapanis: String,
kapali: {type: Boolean, required: true}
});
var yorumSema = new mongoose.Schema({
ad: String,
puan: {type: Number, required: true, min:0, max:5},
yorumMetni: String,
saat: {type: Date, default: Date.now}
});
var mekanSema = new mongoose.Schema({
ad: {type: String, required: true},
adres: String,
puan: {type: Number, default:0, min:0, max:5},
imkanlar: [String],
mesafe: {type: [Number], index:'2dsphere'},
saat: [saatSema],
yorumlar: [yorumSema]
});
mongoose.model('Mekan', mekanSema, 'Mekanlar');
and mekanlar.js file in /app_api/controllers
var mongoose = require('mongoose');
var mekan = mongoose.model('Mekan');
var jsonCevapYolla = function(res, status, content){
res.status(status);
res.json(content);
};
module.exports.mekanGetir = function(req, res){
if (req.params && req.params.mekanid){
Mekan
.findById(req.params.mekanid)
.exec(function(hata, mekan){
if(!mekan){
jsonCevapYolla(res, 404, {
"mesaj" : "mekanid bulunamadı."
});
return;
}
else if(hata){
jsonCevapYolla(res, 404, hata);
return;
}
jsonCevapYolla(res, 200, mekan);
});
}
else{
jsonCevapYolla(res, 404, {
"mesaj" : "istekte mekanid yok"
});
}
};
and this is index.js in /app_api/routes.
var express = require('express');
var router = express.Router();
var ctrlMekanlar = require('../controllers/mekanlar');
var ctrlYorumlar = require('../controllers/yorumlar');
//Mekan Rotaları
//router.get('/mekanlar', ctrlMekanlar.mekanlariListele);
//router.post('/mekanlar', ctrlMekanlar.mekanEkle);
router.get('/mekanlar/:mekanid', ctrlMekanlar.mekanGetir);
//router.put('/mekanlar/:mekanid', ctrlMekanlar.mekanGuncelle);
//router.delete('/mekanlar/:mekanid', ctrlMekanlar.mekanSil);
//Yorum Rotaları
//router.post('/mekanlar/:mekanid/yorumlar', ctrlYorumlar.yorumEkle);
//router.get('/mekanlar/:mekanid/yorumlar/:yorumid', ctrlYorumlar.yorumGetir);
//router.put('/mekanlar/:mekanid/yorumlar/:yorumid', ctrlYorumlar.yorumGuncelle);
//router.delete('/mekanlar/:mekanid/yorumlar/:yorumid', ctrlYorumlar.yorumSil);
module.exports = router;
it's difficult to see where the problem is, since you don't provide a stack trace. but I think at this line:
Mekan
.findById(req.params.mekanid)
Mekan should be mekan.

Can't get mongoose.js to expire old documents at the right time

According to http://mongoosejs.com/docs/api.html#schema_date_SchemaDate-expires I can expire old documents by adding an 'expires' attribute to a mongoose schema. The documents do get removed, when I use the code below, but after around 4 minutes instead of 10 (I've also tried with much higher numbers and e.g. the number 600 instead of '10m').
Any help is appreciated.
Versions:
mongoose: 3.8.12
MongoDB: 2.4.9
// models.js --------------------------------------------------------
var mongoose = require('mongoose');
var signupSchema = mongoose.Schema({
email: {type: String, required: true, unique: true},
token: {type: String, required: true, unique: true},
createdAt: {type: Date, expires: '10m'}
});
signupSchema.pre('save', function(next) {
this.createdAt = Date.now();
next();
});
mongoose.model('Signup', signupSchema);
// user.js (the code below is in a route) ---------------------------
var mongoose = require('mongoose');
var SignupModel = mongoose.model('Signup');
var newSignup = new SignupModel({
email: 'a#a.a',
token: 'token'
});
newSignup.save(function(err, signup) {
// do stuff
});

Resources