mongoose setting referenceone - javascript

Hello can someone help me. I can't set mongoose model field
Here my institute.js model file
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var instituteSchema = new Schema({
name: {type: String, required: true},
idApi: {type: String, required: true},
country: {
type: Schema.ObjectId,
ref: 'Country'
},
created_at: {type: Date, default: Date.now}
}, {collection: 'qel_par_institute', versionKey: false});
instituteSchema.methods.findByIdApi = function (id, callback) {
return mongoose.model('Institute').findOne().where('idApi').equals(id).exec(callback);
}
instituteSchema.methods.findByCountry = function (id, callback) {
return mongoose.model('Institute').find().where('country.id').equals(id).exec(callback);
}
mongoose.model('Institute', instituteSchema);
There the part of sync.js Persisting works except i can't either manually set the country ref neither another field
var instituteApi = new instituteModel({
name: item.name,
idFromApi: item.id
});
if (typeof item.country.id !== 'undefined') {
var country = new countryModel();
country.findByIdApi(item.country.id, function(err, res) {
if (err)
console.log(err);
if (res) {
instituteApi.country = res._id; //setting this way doesn't work
}
})
}
instituteApi.save(function(err) {
if (err)
console.log('something went wrong while saving!');
});

Couldn't set it because async call. Switched callback to promise with Q module. Everything works as wanted

Related

I get this error: this.$__.validationError = new ValidationError(this)

I am new to learning web dev using node.js and express.js. When I test my code in Postman the server crashes and gives me this error this.$__.validationError = new ValidationError(this).
I am creating backend server connected to MongoDB and the mongoose package.
Routes
const express = require('express')
const router = express.Router()
const {
create
} = require('./../controllers/courseControllers')
const {verifyAdmin, verify} = require('./../auth')
router.post('/create', verifyAdmin, async (req, res) => {
// console.log(req.body)
try{
create(req.body).then(result => res.send(result))
}catch(err){
res.status(500).json(err)
}
})
Controllers
const Course = require('../models/Course');
//CREATE A COURSE
module.exports.create = async (reqBody) => {
const {courseName, description, price} = reqBody
let newCourse = new Course({
courseName: courseName,
description: description,
price: price
})
// console.log(newCourse)
return await newCourse.save().then((result, err) => result ? result : err)
}
Schema
const mongoose = require('mongoose');
const courseSchema = new mongoose.Schema({
courseName: {
type: String,
required: [true, `Course name is required`],
unique: true
},
description: {
type: String,
required: [true, `Course description is required`]
},
price: {
type: Number,
required: [true, `Price is required`]
},
isOffered: {
type: Boolean,
default: true
},
enrollees: [
{
userId: {
type: String,
required: [true, `userId is required`]
},
enrolledOn: {
type: Date,
default: new Date()
}
}
]
}, {timestamps: true})
module.exports = mongoose.model("Course", courseSchema);
Given the information you provided, i can say that you are missing the enrollees parameter on creation whitin the controller, as enrollees has been set to required, i hope its usefull for you, if not let me know.

Mongoose populate replacing ObjectIds with empty array

I've been trying to use the mongoose populate function to connect two models. I can save an object but when trying to retrieve using populate the ObjectIds are just replaced with an empty array.
Many questions seem to have been asked but none have a solution that worked for me
user.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var Route = require('./route')
var passportLocalMongoose = require('passport-local-mongoose');
const postSchema = new Schema ({
text: {
type: String,
default: '',
required: true
}
}, {
timestamps: true
});
const UserSchema = new Schema({
firstname: {
type: String
},
posts: [postSchema],
route: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Route'
}]
}, {
timestamps: true
});
UserSchema.plugin(passportLocalMongoose);
const User = mongoose.model('User', UserSchema);
module.exports = User;
route.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
const locationSchema = new Schema ({
id: {
type: Number,
default: 0,
required: true
},
address: {
type: String,
default: '',
required: true
},
lat: {
type: Number,
default: 0,
required: true
},
lng: {
type: Number,
default: 0,
required: true
}
},{
timestamps: true })
const routeSchema = new Schema ({
locations: [locationSchema],
description: {
journey1: {
type: String,
default: '',
required: false
},
journey2: {
type: String,
default: '',
required: false
},
journey3: {
type: String,
default: '',
required: false
},
journey4: {
type: String,
default: '',
required: false
}
}
}, {
timestamps: true
});
module.exports = mongoose.model('Route', routeSchema);
within REST POST end point
User.findOne({_id: req.user._id}, function(err,user) {
if(user) {
var routed = new Route();
routed.locations = req.body.locations;
routed.description = req.body.description;
user.route.push(routed);
user.save()
.then((user) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json')
res.json(user)
}, (err) => next(err))
} else {
console.log("errored")
err = new Error('User ' + req.body.username + ' not found');
err.status = 404;
return next(err);
}
})
within REST GET end point
User.findOne({_id: req.user._id})
.populate('route')
.then((user) => {
if(user){
console.log("user")
console.log(user)
console.log("routes")
console.log(user.route)
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json')
res.json({success: true, routes: user.route});
}
}, (err) => next(err))
.catch((err) => next(err));
If I remove populate I'll get something like
[
new ObjectId("61f053af7ba46267f4893f8f")
new ObjectId("61f053af7ba46267f4893f8f")
new ObjectId("61f053af7ba46267f4893f8f")
]
from the GET end point but adding it back in returns
[].
My understanding is that in 'new Route()' I'm creating a new Route Object with an Id that gets stored in the User model/document(?). Then when I call populate mongoose searches the Route document for those Ids and converts them to the objects I want. The only issue I could think of is that I'm not creating the Route objects correctly and so no object is being stored with that Id which is why an empty array is returned when I come to try swap Ids with Route objects.
Any ideas or are we all just stumbling in the dark ?
Not entirely sure this is the correct method but instead of instantiating a Route object as displayed I used the Route.create(...) method and then pushed that to the route array and now populate works as expected

Mongoose - When returning all items from a collection (with no search param) the returned items from the collection do not contain their mongo _id

I am having a bit of an issue with Mongoose/MongoDB this afternoon. I have a situation where I need to return all items from a collection, and doing so means that I do not pass in any search params to mongoose.find().
This is the controller that handles the get all request:
exports.get_all_posts = async (req, res, next) => {
const { params } = req;
const { sortby } = params;
//Sortby param takes two arguments for now: most_recent, oldest
try {
const getAllPosts = await BlogPost.find({}, { _id: 0 });
console.log(getAllPosts);
if (!getAllPosts) throw new Error('Could not get blog posts.');
res.json({
posts: date_.sort(getAllPosts, sortby)
});
} catch (error) {
next(error);
}
};
This is particularly where I think the issue is coming from:
const getAllPosts = await BlogPost.find({}, { _id: 0 });
I am passing an empty search parameter and then removing the _id so that it doesn't throw an error telling me that I need to provide the _id.
However I still need to be able to pull in all of the posts. My items from this collection return as normal, just without their _id's.
Here is my model for the blog posts:
const mongoose = require('mongoose');
const BlogPostSchema = new mongoose.Schema({
date: {
type: Date,
required: true
},
title: {
type: String,
required: true
},
author: {
type: String,
required: true
},
likes: {
type: Number,
required: false
},
post_body: {
type: String,
required: true
},
description: {
type: String,
required: true
},
tags: [
{
type: String,
required: false
}
],
featuredImage: {
type: String,
required: false
},
draft: {
type: Boolean,
required: true
}
});
module.exports = mongoose.model('BlogPost', BlogPostSchema);
One thing to note is that I have not defined an _id. Mongoose automatically adds in the _id field before saving a schema, so I think it is okay without it, as it has been in the past.
Thanks in advance for reading and any input!
Just as Joe has commented, { _id: 0 } as the second parameter is making your query not return the _id field.
Also as he said, there should be no problem whatsoever with using find({}).
Since other than what has already been stated, I couldn't figure out any mistake in the code snippets you provided, I guess this error could be coming from somewhere else in your project.
exports.get_all_posts = async (req, res, next) => { const { params } = req; const { sortby } = params;
try { const getAllPosts = await BlogPost.find({}); console.log(getAllPosts); if (!getAllPosts) throw new Error('Could not get blog posts.'); res.json({ posts: date_.sort(getAllPosts, sortby) }); } catch (error) { next(error); } };
no need to {_id:0} in the find() method because this method retrieve all the documents in the db collection

save and populate node js

I have Course Schema like below
const studentSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
current_education: {
type: String,
required: true
},
course_name: {
type: mongoose.Schema.Types.ObjectId,
ref:'Course'
},
address: {
type: String,
required: true
},
mobile_number: {
type: Number,
required: true
},
date: {
type: Date,
default: Date.now
}
})
and I'm trying to make relationship student to the course. In the controller, I'm trying to populate the course details based on the course ID like below
exports.createStudent = async (req, res) => {
try {
const student = new Student(req.body);
const result = await student.save().then(t => Course.findById(req.body.course_name).populate('courses'));
if (!result) res.send('something went wrong');
res.send(result)
} catch (e) {
res.send(e);
}
}
In the postman how I'm posting you can check it below
{
"name":"Ram",
"current_education":"B.tech",
"course_name":"5cb804f1e97ba91cb8ca9dac",
"address":"Bangalore",
"mobile_number":7894561236
}
Important: Here courseID is existed in the database
the data is saved successfully in the database but the course details not populated except id. the resultant data in the database look like below
I guess you want Student details along with the course details:
Here's how you achieve it:
exports.createStudent = async (req, res) => {
try {
const student = new Student(req.body);
const result = await student.save().then(t =>
Student.findById(student._id).populate('course_name')); // Pass new ID and then populate the "course_name"
if (!result) res.send('something went wrong');
res.send(result)
} catch (e) {
res.send(e);
}
}
Hope this solves your query!

MongoDB/mongoose - Post save hook not running

I have this model/schema:
const InviteSchema = new Schema({
inviter: {type: mongoose.Schema.Types.ObjectId, ref: 'Account', required: true},
organisation: {type: mongoose.Schema.Types.ObjectId, ref: 'Organisation', required: true},
sentTo: {type: mongoose.Schema.Types.ObjectId, ref: 'Account', required: true},
createdAt: {type: Date, default: new Date(), required: true}
});
InviteSchema.post('save', function(err, doc, next) {
// This callback doesn't run
});
const Invite = mongoose.model('Invite', InviteSchema);
module.exports = Invite;
Helper function:
exports.sendInvites = (accountIds, invite, callback) => {
let resolvedRequests = 0;
accountIds.forEach((id, i, arr) => {
invite.sentTo = id;
const newInvite = new Invite(invite);
newInvite.save((err, res) => {
resolvedRequests++;
if (err) {
callback(err);
return;
}
if (resolvedRequests === arr.length) {
callback(err);
}
});
});
};
And the router endpoint which calls the helper function:
router.put('/organisations/:id', auth.verifyToken, (req, res, next) => {
const organisation = Object.assign({}, req.body, {
updatedBy: req.decoded._doc._id,
updatedAt: new Date()
});
Organisation.findOneAndUpdate({_id: req.params.id}, organisation, {new: true}, (err, organisation) => {
if (err) {
return next(err);
}
invites.sendInvites(req.body.invites, {
inviter: req.decoded._doc._id,
organisation: organisation._id
}, (err) => {
if (err) {
return next(err);
}
res.json({
error: null,
data: organisation
});
});
});
});
The problem here is that the .post('save') hook doesn't run, despite following the instructions, i.e. using .save() on the model instead of .findOneAndUpdate for example. I've been digging for a while now but I cannot see what the problem here could be.
The Invite document(s) are saved to the database just fine so the hook should fire, but doesn't. Any ideas what could be wrong?
You can declare the post hook with different number of parameters. With 3 parameters you are treating errors, so your post hook will be called only when an error is raised.
But, if your hook has only 1 or 2 parameters, it is going to be executed on success. First parameter will be the document saved in the collection, and second one, if passed, is the next element.
For more information, check official doc: http://mongoosejs.com/docs/middleware.html
Hope it helps.

Categories

Resources