Catch error when using populate with mongoose - node.js

I have the next model and route with mongoose:
In my colection I have some invalids id's to "cidade" field and this is why I am getting the error showing below.
The error happens in the line:
.populate('cidade')
Is there a way to execute my router(code is below) in:
router.get('/:id',function(req,res,next){ .....
without stop on that error?
If an invalid "id" is found, I´d just like to ignore it and proceed to next.
My collections are too big and can have some invalids "ids" to "cidade" field.
//error
angular.js:14328 Possibly unhandled rejection: {"data":{"message":"Cast to ObjectId failed for value \"Ararendá\" at path \"_id\" for model \"Cidade\"","name":"CastError","stringValue":"\"Ararendá\"","kind":"ObjectId","value":"Ararendá","path":"_id"},"status":500,"config":
//models and route
//cidade
cidadesSchema = new mongoose.Schema({
uf: {type: String, unique:true},
cidade: {type: String, unique:true}
});
module.exports = mongoose.model('Cidade', cidadesSchema,'cidades' );
//profiss
var profissionaisSchema = new mongoose.Schema({
nome: {type: String, unique:true},
cidade: {type:mongoose.Schema.Types.ObjectId, ref:'Cidade'},
estado: {type:mongoose.Schema.Types.ObjectId, ref:'Estado'},
cep: {type: String},
});
module.exports = mongoose.model('Profissional', profissionaisSchema,'profissionais' );
//route
const callback=function(err,data,res){
if (err) return res.status(500).json(err);
return res.status(200).send(data);
}
router.get('/:id',function(req,res,next){
const query=req.params.id;
Profissional.findById(query).populate('profissao')
.populate('cidade')
.exec( (err,data) => {
callback(err,data,res)
});
});

I don't think you can tell Mongoose to just ignore those errors and keep going, so you're going to have to implement the population yourself (which should be relatively easy because you're using findById which would only yield, at most, one document).
Here's some (untested) code:
Profissional.findById(query).populate('profissao').exec( (err, profi) => {
if (err) {
return res.status(500).json(err);
} else if (! profi || ! /^[a-f0-9]{24}$/i.test(profi.cidade)) {
return res.status(200).send(profi);
}
Cidade.findById(profi.cidade).exec((err, cidade) => {
if (err) {
return res.status(500).json(err);
}
profi.cidade = cidade;
return res.status(200).send(profi);
});
});
If the cidade property looks like a valid ObjectId, it will run a query to retrieve it, otherwise it won't bother.

Related

Can we Insert data in Object collection in Mongodb

Can anyone please help i tried to insert data in object, but not using array.
I need output like this
{"_id":{"$oid":"5bacbda18ffe1a2b4cb9b294"},
"type":{"name":"prudhvi",
"headings":["Abstract","Introduction","Models"]}}
but i am getting like this
{"_id":{"$oid":"5c52d7484c7644263cbc428a"},
"name":"prudhvi",
"headings":["Abstract","Introduction","Models"],
"__v":{"$numberInt":"0"}}
and I wrote my Collection like this
var articleTypeSchema = new mongoose.Schema({
type: { type: mongoose.Schema.Types.Object, ref: 'typeSchema' }
});
var typeSchema = {
name:String,
headings:[String],
};
var Collections = {
type: mongoose.model('article_types',typeSchema)
}
This is my backend what i wrote
userRouter.post('/addarticletype',(req,res)=>{
Collections.type.create({name:req.body.type,headings:req.body.head},function(err,result){
if (err) return res.status(500).send("There was a problem adding the information to the database");
else
res.status(200).send(result);
console.log(result);
})
})
In your model, change the data type to JSON instead of String and then when you are trying to create a new collection
var typeSchema = {
type:JSON,
};
Step 2: While creating collection, create a JSON object for that key.
userRouter.post('/addarticletype',(req,res)=>{
Collections.type.create({type:{name:req.body.type,headings:req.body.head}},function(err,result){
if (err)
return res.status(500).send("There was a problem adding the information to the database");
else
res.status(200).send(result);
console.log(result);
})
})
Step 3 : Done
You need to rewrite the model as below:
var typeSchema = new mongoose.Schema ({
name:String,
headings:[String],
});
var articleTypeSchema = new mongoose.Schema({
type: { type: mongoose.Schema.Types.Object, ref: 'typeSchema' }
});

Mongoose can't save document to the database for one particular collection

I have a function
function generateInvoice(data) {
const cdate = new moment.tz('GMT').toDate();
let invoiceData = {
date: cdate,
paidStatus: true,
amount: data.amount,
userId: data.userId
}
if (data.planName && data.planTypeName) {
invoiceData.item = `${data.planName} - ${data.planTypeName}`
invoiceData.quantity = data.seats || data.slots;
}
if (data.credits) {
invoiceData.item = 'Credits';
invoiceData.quantity = data.credits;
}
return Invoice.create(invoiceData).then((data)=>{
data.invoiceId = data._id.toString().slice(-5);
return data.save().then((data)=>{console.log(data); return data.invoiceId}).catch((err)=>{
throw new ErroWithStatusCode(500, 'Sorry, we seem to be facing some issue right now. Please, try again later.', err);
})
})
}
and this is how I am using this function
return generateInvoice(invoiceData).then((data)=>{
newBooking.orderId = data;
id = data;
return newBooking.save().then((booking) => {
return booking;
}).catch((err) => {
throw new ErroWithStatusCode(500, 'Sorry, we are facing some issue right now. Please try again later.')
})
});
The issue is that I can't find invoiceData in my invoices collection. The data in the callback function of then block is the document, but I can't find the same document in the invoices collection.
All the promises are getting resolved. It is not falling in the catch block, I am receiving valid data from Invoice.create(invoiceData).
Also, newBooking.save() function is working as expected. So, that's what is bothering me the most, as to why is it not working for one specific collection.
What could be the reason behind it?
EDIT: This is the invoice schema
const InvoiceSchema = new Schema({
item: String,
paidStatus: Boolean,
quantity: String,
amount: Number,
invoiceId: String,
userId: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
date: {type: Date, default: Date.now()},
__v: {type: Number, select: false}
}, {strict: true})
export default mongoose.model('Invoice', InvoiceSchema);
And I am not receiving any error, the booking is successful. I tried logging the data received in the then block, and it is a valid document, as I have already mentioned above.
EDIT: The following is the complete code that invovlves the use of generateInvoice function: book.js
Insted of
return Invoice.create(invoiceData).then((data)=>{...
Try
new Invoice(invoiceData).save((err,data)=>{
if(err) return console.log(err);
return data._id;
})

Mongoose Version Error and no matching document found for id

I have a mongoose schema, and I just added the field "imagens" in the original schema.
The field added is:
imagens:[{title:{type: String},savedAs:{type: String},file:{type: String}, thumb:{type: String}}],
Now when I try fill the 'imagens' field and update the collection, I get the next error.
And if I get rid off the line 'item.imagens=imgs' the error is gone.
What am I doing wrong? Is there some fix to this problem?
//Error
{"data":{"message":"No matching document found for id \"5909caeed32a453b537f7966\"",
"name":"VersionError"}, "status":500,
"config":{"method":"POST","transformRequest":[null],"transformResponse":[null],"jsonpCallbackParam":"callback",
"url":"/uploads",
"data":{"file":{"$ngfBlobUrl":
"blob:http://localhost/9c4b0449-1ddd-4e39-ab44-f2e9a21bfd82","$ngfWidth":450,"$ngfHeight":321,
"upload":{},"progress":100},"pacID":"5909caeed32a453b537f7966"},"_isDigested":true,
"_chunkSize":null,"headers":{"Accept":"application/json, text/plain, */*"},"_deferred":{"promise":"..."},"cached":false},"statusText":"Internal Server Error"}
//in my router
Cliente.findById(pac_id, function (err, item) {
if (err) {
return res.status(500).send(err);
} else {
item.imagens=imgs
}
item.save(function (err, data) {
if (err) {
return res.status(500).send(err)
}
if (answers.results.length){
answers.message='Some files was not uploaded'
} else {
answers.message='Files were uploaded'
}
res.send(answers)
})
})
//model
const mongoose=require('mongoose');
const clientesSchema = new mongoose.Schema({
id: {type: Number, unique:true},
nome: {type: String, unique:true},
ativo: {type: Boolean},
...
...
foto: { data: Buffer, contentType: String },
imagens:[{title:{type: String},savedAs:{type: String},file:{type: String}, thumb:{type: String}}],
created_at:{type:Date,default:Date.now},
altered_at:{type:Date,default:Date.now}
});
module.exports = mongoose.model('Cliente', clientesSchema,'clientes' );
Delete the document version, that will resolve the version conflict.
Then Mongoose will allow you to save :
delete item.__v
item.save(...)

Mongoose NodeJS Schema with array of ref's

I know there is allot's of answers about it but still I didn't quite get the idea.
I have CourseSchema:
const CourseSchema = new Schema({
course_name: String,
course_number: {type: String, unique : true },
enrolledStudents:[{
type: mongoose.Schema.Types.ObjectId,
ref: 'Student' }]
});
And a StudentSchema:
const StudentSchema = new Schema({
first_name: String,
last_name: String,
enrolledCourses:[{
type: mongoose.Schema.Types.ObjectId,
ref: 'CourseSchema'
}]
});
I want to reffer enrolledStudents at CourseSchema with a student, and enrolledCourses at StudentSchema with a course.
router.post('/addStudentToCourse', function (req, res) {
Course.findById(req.params.courseId, function(err, course){
course.enrolledStudents.push(Student.findById(req.params.studentId, function(error, student){
student.enrolledCourses.push(course).save();
})).save();
});
});
but when posting I get an error:
TypeError: Cannot read property 'enrolledStudents' of null
Ok so after readying Query-populate I did that:
router.post('/addStudentToCourse', function (req, res) {
Course.
findOne({ _id : req.body.courseId }).
populate({
path: 'enrolledStudents'
, match: { _id : req.body.studentId }
}).
exec(function (err, course) {
if (err) return handleError(err);
console.log('The course name is %s', course.course_name);
});
});
And when i'm hitting POST on postman I get on the console:
The course name is intro for cs
but it is loading for ever and later on console I get:
POST /courses/addStudentToCourse - - ms - -
You are missing the populate instruction. For example:
see more about it here
Course.
findOne({ courseId : req.params.courseId }).
populate('enrolledStudents').
exec(function (err, course) {
if (err) return handleError(err);
console.log('The course name is %s', course.name);
});
It is working by using the ref field that "knows" how to populate withput using the push syntax. it is like a foreign key population.
Just call the populate method on the query and an array of documents will be returned in place of the original _ids. you can learn more on the internals of the populate methods in the official docs

Trying to update nested / subdocument in Express

I have a Mongoose model that has nested array and a subdocument.
I seem to be ok when posting to the object arrays/subdocument, but I'm having trouble with the .put
I hard coded the params for testing, just in case they were not coming in from PostMan for some reason.
The result I get from the above code is an empty array!
So I'm getting the right record and it creates the "phone" array, but does not populate.
.put(function(req, res){
Member.find({'_id':req.params.id}, function(err, member){
if(err)
res.send(err);
member.phone.push({
number: "78787878787",
phoneType: 2
})
member.save(function(err){
if(err)
res.send(err);
res.json(member);
});
});
});
I want to have an endpoint that simply adds another "phone" record.
Here is my model:
//DEPENDENCIES
var mongoose = require('mongoose');
var contactSchema = new mongoose.Schema({
name:{type:String},
age:{type:Number}
});
var phoneSchema = new mongoose.Schema({
number:{ type: String },
phoneType:{ type: Number }
})
var memberSchema = new mongoose.Schema({
firstname: {
type: String
},
lastname: {
type: String
},
phone:[phoneSchema],
contacts:[contactSchema]
});
//RETURN MODEL
module.exports = mongoose.model('member', memberSchema);
Now when I run my code I get the following undefined for "members":
{ id: '587bcbffe64e9f28a6894dd7' }
[ { _id: 587bcbffe64e9f28a6894dd7,
lastname: 'Stanley',
firstname: 'Dave',
__v: 0,
contacts: [ [Object] ],
phone: [] } ]
events.js:154
throw er; // Unhandled 'error' event
^
TypeError: Cannot read property 'push' of undefined
find returns an array of documents, not just one document. Thats is why it is giving error when you are trying to do member.phone.
Use findOne instead of find as you are querying by _id, it will return only one matched document or null(if its not present), so its a better choice than find.
Also, its better to check if the result is null or not. member will be null if no such _id is present.
Member.findOne({'_id':req.params.id}, function(err, member){
if(err)
res.send(err);
else if(member!=null)
{
member.phone.push({
number: "78787878787",
phoneType: 2
});
member.save(function(err){...});
}
});
If you are keen on using find. Use member[0] (first element) instead of member.
Member.find({'_id':req.params.id}, function(err, member){
if(err)
res.send(err);
else if(member.length!=0)
{
member[0].phone.push({
number: "78787878787",
phoneType: 2
});
member[0].save(function(err){...});
}
});
Hope that helps you.

Resources