I'm trying to save an mongoose object to db, but it doesn't work (nothing is saved, and no callback returned). The database is open, and there is a successful connection (the collection is even created according to the model, and it indexing it).
my schema:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var CourseSchema = new Schema({
providerId: {type: String, required: true, unique: true},
from: {
provider: {type: String, required: true},
creators: [String]
},
name: {type: String, required: true},
link: {type: String, required: true},
textualInfo:{
summery: String,
longDescription: String,
syllabus: String,
subjects: [String]
},
media: {
image: String,
trailer: String
},
meta:{
languages: [String],
level: Number,
workload: String,
duration: String,
prerequirments: String,
priceDollars: Number,
enrollments: Number,
},
dateCreated: {type: Date, default: Date.now},
dateLocalModified: {type: Date},
queries: [String]
});
CourseSchema.index({
'from.provider': 'text',
'from.creators': 'text',
'name': 'text',
'textualInfo.summery': 'text',
'textualInfo.longDescription': 'text',
'textualInfo.syllabus': 'text',
'textualInfo.subjects': 'text'
},{
name: 'search index', weights: {
'from.provider': 120,
'from.creators': 120,
'name': 150,
'textualInfo.summery': 20,
'textualInfo.longDescription': 2,
'textualInfo.syllabus': 1,
'textualInfo.subjects': 20
}});
CourseSchema.pre('save', function(next) {
var course = this;
course.dateLocalModified = new Date();
if(!course.isModified('providerId')) return next();
if(!(/#/.test(course.providerId))){
course.providerId = course.providerId + '#' + course.from.provider;
}
});
var Course = mongoose.model('Course', CourseSchema);
module.exports = Course;
the insertion test code:
var Course = require('./course');
var mongoose = require('mongoose');
mongoose.connect('mongodb://127.0.0.1:27017/mydb',{
server: {socketOptions: { keepAlive: 1 }},
replset: {socketOptions: { keepAlive: 1 }}
});
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function (callback) {
console.log('mongoose is connected to db');
var course = new Course({
providerId: 'pid123',
from: {
provider: 'test',
creators: ['creators']
},
name: 'test course',
link: 'http://testlink.com',
textualInfo:{
summery: 'c.shortDescription',
longDescription: 'c.aboutTheCourse',
syllabus: 'c.courseSyllabus',
subjects: ['subjNames'],
},
media: {
image: 'c.photo',
trailer: "https://www.youtube.com/watch?v="
},
meta:{
languages: [],
level: 0,
workload: 'c.estimatedClassWorkload',
duration: "",
prerequirments: 'c.recommendedBackground',
priceDollars: 0,
enrollments: 0,
},
queries: []
});
console.log('trying to save:', course.name);
course.save(function(err){
console.log(err);
db.close();
});
});
db.on('disconnected', function () {
console.log('Mongoose default connection disconnected');
});
Thanks for the help!
This is necromancy :D but maybe it will help someone.
I think the issue is with the "pre save" function,
it only returns the callback in one if. If you do not go inside the if a callback is never called.
Adding a
return next();
At the end of the "CourseSchema.pre('save', function(next)" should fix the issue for you.
Related
/I want to create a module section for a course website for which I will need a lesson schema as well so How can I design lesson schema , module schema , and course schema so they
work just how they are needed to workCurrently I am doing this/
import mongoose from 'mongoose'
const LessonSchema = new mongoose.Schema({
title: String,
content: String,
resource_url: String
})
const ModuleSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
lessons: [LessonSchema]
})
export const Module = mongoose.model('Module', ModuleSchema);
const CourseSchema = new mongoose.Schema({
name: {
type: String,
trim: true,
required: 'Name is required'
},
price: {
type: String,
trim: true,
required: true
},
image: {
data: Buffer,
contentType: String
},
intro: {
type: String,
required :true
},
description: {
type: String,
trim: true
},
category: {
type: String,
required: 'Category is required'
},
updated: Date,
created: {
type: Date,
default: Date.now
},
instructor: {type: mongoose.Schema.ObjectId, ref: 'User'},
published: {
type: Boolean,
default: false
},
modules: [ModuleSchema]
})
export default mongoose.model('Course', CourseSchema)
Above was the schema and this is logic
const newLesson = async (req, res) => {
try {
let lesson = req.body.lesson
let course = await Course.find({modules: {_id: req.params.moduleId}})
console.log(course)
} catch (err) {
return res.status(400).json({
error: errorHandler.getErrorMessage(err)
})
}
}
const newModule = async (req, res) => {
try {
let lesson = req.body.lesson
let result = await Course.findByIdAndUpdate(req.course._id, {$push: {modules: {name: req.body.name, lessons: lesson}}, updated: Date.now()}, {new: true})
.populate('instructor', '_id name')
.exec()
res.json(result)
} catch (err) {
return res.status(400).json({
error: errorHandler.getErrorMessage(err)
})
}
}
**I have been brainstorming this from a while and cant get through it do you know how can I shape the schema and logic so that I can push lessons in module and then module in course schema ? **
I want to find a document in my db and replace it with a document that has a new name and new key.
Here is my Schema
const Schema = mongoose.Schema;
const vampireSchema = new Schema({
name: { type: String, required: true },
title: String,
hair_color: {type: String, default: "blonde" },
eye_color: String,
dob: Date,
loves: [String],
location: String,
gender: String,
victims: {type: Number, min: 0}
});
const Vampire = mongoose.model("Vampire", vampireSchema);
module.exports = Vampire;
Here is my executable code
Vampire.findOneAndReplace( { name: "Claudia" }, { name: "Eve", portrayed_by: "Tilda Swinton" }, (err, vamp) => {
if(err){
console.log(err)
}
else{
console.log(vamp)
}
db.close()
})
There are two issues that I can see.
First, you should pass null as the third argument in your findOneAndReplace call. This will set the options to null and should get your code running. This is in my opinion a strange behavior of mongoose.
Vampire.findOneAndReplace(
{ name: "Claudia" },
{ name: "Eve", portrayed_by: "Tilda Swinton" },
null,
(err, vamp) =>
{
if(err){
console.log(err)
}
else{
console.log(vamp)
}
db.close()
})
Secondly, I would recommend adding the portrayed_by to the schema, otherwise, that field will not be in the newly created document. Therefore, I would adjust your schema that way:
const vampireSchema = new Schema({
name: { type: String, required: true },
title: String,
hair_color: {type: String, default: "blonde" },
eye_color: String,
dob: Date,
loves: [String],
location: String,
gender: String,
victims: {type: Number, min: 0},
portrayed_by: String
});
I am building ecommerce website using MERN stack. And I am getting error while testing using Postman.
backend/controllers/user.js
const User = require("../models/user");
const Order = require("../models/order");
exports.userPurchaseList = (req, res) => {
Order.find({ user: req.profile._id })
.populate("user", "_id name")
.exec((err, order) => {
if (err) {
return res.status(400).json({
error: "No Order in this account",
});
}
return res.json(order);
});
};
backend/models/Order.js
const mongoose = require("mongoose");
const { ObjectId } = mongoose.Schema;
const ProductCartSchema = new mongoose.Schema({
product: {
type: ObjectId,
ref: "Product",
},
name: String,
count: Number,
price: Number,
});
const ProductCart = mongoose.model("ProductCart", ProductCartSchema);
const OrderSchema = new mongoose.Schema(
{
products: [ProductCartSchema],
transaction_id: {},
amount: { type: Number },
address: String,
status: {
type: String,
default: "Recieved",
enum: ["Cancelled", "Delivered", "Shipped", "Processing", "Recieved"],
},
updated: Date,
user: {
type: ObjectId,
ref: "User",
},
},
{ timestamps: true }
);
const Order = mongoose.model("Order", OrderSchema);
module.exports = { Order, ProductCart };
backend/models/User.js
const mongoose = require("mongoose");
const crypto = require("crypto");
const uuidv1 = require("uuid/v1");
var userSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
maxlength: 32,
trim: true,
},
lastname: {
type: String,
maxlength: 32,
trim: true,
// required: false,
},
email: {
type: String,
required: true,
trim: true,
unique: true,
},
userinfo: {
type: String,
trim: true,
},
encry_password: {
type: String,
required: true,
},
salt: String,
role: {
type: Number,
default: 0,
},
purchases: {
type: Array,
default: [],
},
},
{ timestamps: true }
);
module.exports = mongoose.model("User", userSchema);
backend/routes/user.js
router.get(
"/orders/user/:userId",
isSignedIn,
isAuthenticated,
userPurchaseList
);
Error:-
TypeError: Order.find is not a function
at exports.userPurchaseList (C:\Users\Rahul\MernBootcamp\projbackend\controllers\user.js:47:9)
TESTING this route using POSTMAN.
You have exported an object so in your backend/controllers/user.js
you could import it like so from destructuring from the object then the rest of your code would be okay
const {Order} = require("../models/order");
or
accessing it using the dot notation
when calling the find Function
//importing it at the top
const Order = require("../models/order");
exports.userPurchaseList = (req, res) => {
Order.Order.find({ user: req.profile._id })
.populate("user", "_id name")
.exec((err, order) => {
if (err) {
return res.status(400).json({
error: "No Order in this account",
});
}
return res.json(order);
});
};
I'm sorry if this might be a duplicate question but I'm quite having a hard time understanding Mongoose. I am working on a Node.js project that implements Mongoose and MongoDB. What I want to accomplish is to modify and save some users' data through a call from a specific endpoint.
Mongoose Schema looks like this
var UserSchema = new Schema({
isAdmin: {type: Boolean, default: false},
name: String,
surname: String,
nickname: { type: String },
email: { type: String, lowercase: true, required: true, trim: true, unique: true, dropDubs: true },
password: { type: String, required: true },
salt: { type: String },
verified: { type: Boolean, default: false },
bio: {
type: { type: String, enum: [0,1] }, // 0='Appassionato', 1='Giocatore'
birthday: String,
height: Number,
number: Number,
role: { type: String, enum: [0,1,2,3] }, // 0='Playmaker', 1='Ala', 2='Guardia', 3='Centro'
team: String,
city: String,
aboutMe: String,
},
newsletter: {type: Boolean, default: false},
lastCheckin: {type: mongoose.Schema.Types.ObjectId, ref: 'Checkin'},
follows: [{type: mongoose.Schema.Types.ObjectId, ref: 'Structure'}],
score: { type: Number, default: 0 },
profilePicture: String,
lastLogin: {type: Date},
facebook: {
id: String,
accessToken: String,
profileImage : String
}
}, {
collection: 'users',
retainKeyOrder: true,
timestamps: true,
}).plugin(mongoosePaginate);
Following is the code for when the endpoint gets interrogated
exports.updateUser = (req,res) => {
var userId = req.params.userId;
var updates = req.body;
User.findOneAndUpdate({_id: userId}, {$set: updates}, (err, saved) => {
if (!err) {
console.log("Ritorno questo: " + saved);
return res.status(202).json(saved);
} else {
return res.status(500).json(saved);
}
});
};
As far as I understood, the method findOneAndUpdate exposed by Mongoose should find the document I'm looking for and then modify it and save it. This doesn't happen though.
Through PostMan I'm sending this JSON
{"bio.aboutMe":"Hello this is just a brief description about me"}
But PostMan is responding with the non-modified object. What am I missing here?
What you need to do is to add {new:true}, it give you back the updated document.
In the documentation :
If we do need the document returned in our application there is
another, often better, option:
> Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, { new: true },
> function (err, tank) { if (err) return handleError(err);
> res.send(tank); });
This is something I don't really like as there is another option if we don't want to have the document → update
So what you need to do is :
User.findOneAndUpdate({_id: userId}, {$set: updates}, {new:true}.....
The following piece of code which works fine. However,when I run it again from my cmd(node server),I get a duplicate key message of the dish name. I have two files. The dishes.js where I define my schemas and make available to my second file called server.js.
dishes
// grab the things we need
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var commentSchema = new Schema({
rating: {
type: Number,
min: 1,
max: 5,
required: true
},
comment: {
type: String,
required: true
},
author: {
type: String,
required: true
}
}, {
timestamps: true
});
// create a schema
var dishSchema = new Schema({
name: {
type: String,
required: true,
unique: true
},
description: {
type: String,
required: true
},
comments:[commentSchema]
},
{
timestamps: true
});
// the schema is useless so far
// we need to create a model using it
var Dishes = mongoose.model('Dish', dishSchema);
// make this available to our Node applications
module.exports = Dishes;
and my server.js file.
var mongoose = require('mongoose'),
assert = require('assert');
var Dishes = require('./models/dishes-3');
// Connection URL
var url = 'mongodb://localhost:27017/conFusion';mongoose.connect(url);
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function () {
// we're connected!
console.log("Connected correctly to server");
// create a new dish
Dishes.create({
name: 'Uthapizza',
description: 'Test',
comments: [
{
rating: 3,
comment: 'This is insane',
author: 'Matt Daemon'
}
]
}, function (err, dish) {
if (err) throw err;
console.log('Dish created!');
console.log(dish);
var id = dish._id;
// get all the dishes
setTimeout(function () {
Dishes.findByIdAndUpdate(id, {
$set: {
description: 'Updated Test'
}
}, {
new: true
})
.exec(function (err, dish) {
if (err) throw err;
console.log('Updated Dish!');
console.log(dish);
dish.comments.push({
rating: 5,
comment: 'I\'m getting a sinking feeling!',
author: 'Leonardo di Carpaccio'
});
dish.save(function (err, dish) {
console.log('Updated Comments!');
console.log(dish);
db.collection('dishes').drop(function () {
db.close();
});
});
});
}, 3000);
});
});
If you pay a close attention in the server.js file I have removed the unique: true attribute from by dishes.js file,but I still have the same problem.
name: {
type: String,
required: true,
unique: true
},
when your schema is given below
name: {
type: String,
required: true,
unique: true
}
the unique is working
when your schema is given below
name: {
type: String,
required: true
}
the unique not working
after change your schema definition, drop all your collection and try to insert.