mongoose - Cast to number failed for value "[object Object]" at path - javascript

I have a schema that looks like this:
module.exports = mongoose.model('Buyer',{
username: String,
password: String,
email: String,
url: String,
id: String,
firstName: String,
lastName: String,
credit: Number,
});
I am trying to add to their credit whenever they submit a Stripe payment, but when I do, I get the error that is in the title:
Cast to number failed for value "[object Object]" at path
Here is where I try to update credit:
var query = Buyer.findOne({'_id': req.user._id});
query.exec(function(err,buyer){
buyer.credit = { credit: parseInt(req.body.amount,10) };
buyer.markModified('credit');
buyer.save(function (err) {
if (!err) {
//--NO ERROR
} else {
return console.log(err);
}
});
});
I'm not sure how to add to existing credit, instead of overwriting it as I'm doing above, but I suppose I'll ask that in another question after looking further into it.
Anyways, I don't understand what is going on with my error. I tried doing it without the parseInt but noticed it was a string.

Change this line:
buyer.credit = { credit: parseInt(req.body.amount,10) };
To:
buyer.credit = req.body.amount;
You just want to set buyer.credit to the value, not another object with its own credit field. You don't need to the parseInt because Mongoose will do that for you based on your definition of credit as a Number in the schema.
You can also remove the buyer.markModified('credit'); line.

Related

Why yup is trigger my tests even though previous tests are failing?

I want to validate my object with the schema using yup.
But I notice that when I wrote my own test function it's trigger anyway.
I mean I validate the age property for number, null, positive, integer value. then I want to continue with my own logic test.
So I expect to NOT enter the function unless the previous tests are valid.
I'm not sure if this is how it meant to be, but in this way I must also check for valid input in my tests function, even though I add the number, null, positive, integer checks.
So am I using the yup wrong?
What I expect form yup is not invoke the test if the previous tests are invalid.
stackblitz
import { object, string, number, date, InferType } from 'yup';
let userSchema = object({
age: number()
.nullable()
.positive()
.integer()
.test({
message: 'test message',
test: (v) => {
console.log('in test!', v);
return !!v.toPrecision();
},
}),
});
userSchema
.validate({ age: null })
.then((res) => {
console.log({ res });
})
.catch((e) => {
console.log({ e });
});

Mongoose automatically change the type of the value

In mongoose.model, I have chosen the type of name to be a string and the type of age to be a number, but when I enter a number as the value of name, I don't get an error and the same thing happens when I use something like '18' as the value of age.
Here is the code:
const User = mongoose.model('User', {
name: { type: String },
age: { type: Number }
});
const me = new User({
name: 12,
age: '18'
});
me.save().then(() => console.log(me)).catch(error => console.log(error));
Mongoose casts the values to the corresponding type, if it fails a CastError is thrown, from the doc:
Before running validators, Mongoose attempts to coerce values to the
correct type. This process is called casting the document. If casting
fails for a given path, the error.errors object will contain a CastError object.
You can try this by given age the value 'aa' for example.
If you want to override this behavior you can use one of the following options:
Disable casting globally: mongoose.Number.cast(false)
Disable casting just for a given path:
age: {
type: Number,
cast: false // Disable casting just for this path
},
Use a custom function:
age: {
type: Number,
cast: v => { return typeof v === 'number' && !isNaN(v) ? Number(v) : v; } // Override casting just for this path
}

return single object based on ObjectId

hi im currently building something for fun that allows users to post anything. and im experincing some problems here is my code.
return details.findOne({'data': {$elemMatch: {'_id':req.params.id}}}).then((a) => {
return res.render('post', { a });
}).catch(err => console.log(err));
i only want this to return one post i thought by using the objectId id would be able todo that but it seems to return everything in the data array anybody have any ideas below is my schema.
i need this to only return the single object whos objId is in the url
var schemaMode = new mongoose.Schema({
email: {type: String, required: true},
password: {type: String, required: true},
username: {type: String,required:true},
data: [{
author: String,
title: String,
comments: [String],
article: String,
}]
});
Details.findById(req.params.id, function(err, foundObject){
//foundObject contains the object with the ._id matching req.params.id
});
if you only want certain fields back, like you want the object to only have its data field for example, then you do:
Details.findById(req.params.id, "data",
function(err, foundObject){
//foundObject contains the object with the ._id matching req.params.id
});
OR
Details.findById(req.params.id).select("data")
.exec(function(err, foundObject){
//foundObject contains the object with the ._id matching req.params.id
});
to be clear, in the code above, Details is the imported (with require) schema (in your case, the one named schemaMode)
Is "data" your "post"? If so, I think you need a projection.
return details.findOne({'data': {$elemMatch: {'_id':req.params.id}}},{'data.$'}).then((a) => {
return res.render('post', { a.data[0] });
}).catch(err => console.log(err));
'data.$' will project you the whole model, filled only with the desired "data"/"post"

JSON object architecture looks different when I pass it to the client side

Here is my Schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var messageSchema = new Schema({
requestNumber: String,
requestedDateTime: String,
reasons: String,
state: String,
hospital: String,
phone: String,
status: {type: String, default: 'Pending'},
latestUpdate: Date,
createdAt: {type: Date, default: Date.now}
});
module.exports = mongoose.model('Requests', messageSchema);
Below I am returning the collection with three components in it
ipcMain.on('load-requests', function(event) {
hosSchemaModel.find(function(err, hosSchema) {
if (err) {
console.log('inside error') // return res.send(err);
} else {
event.sender.send('requests-results', hosSchema) // this line of code passes hosSchema to the client side
console.log(hosSchema[0].state) //prints the state attribute of the first component in the collection without any errors.
}
});
});
When I try to console.log(hosSchema) in the server, I get the following printed to the terminal:
and I could successfully access the properties such as status of the first component in the collection by referring to its index hosSchema[0].status.
Below I am trying to print hosSchema to the console (in the front-end)
ipcRenderer.on('requests-results', (event, hosSchema) => {
console.log(hosSchema)
})
I get the result different from what they were looking in the terminal. below is the picture
and hosSchema[0].status returns undefined.
My questions are:
1) why hosSchema[0].status doesn't work in the front-end?
2) what is the correct way to access the properties in the client-side?
All you have to do in the front end is to use hosSchema[0]._doc.status instead of hosSchema[0].status

Stripping unknown keys when validating with Joi

I'm using Joi to validate a JavaScript object in the server. The schema is like the following:
var schema = Joi.object().keys({
displayName: Joi.string().required(),
email: Joi.string().email(),
enabled: Joi.boolean().default(false, "Default as disabled")
}).unknown(false);
The schema above will report an error if there is an unknown key in the object, which is expected, but what I want is to strip all the unknown silently, without an error. Is it possible to be done?
You need to use the stripUnknown option if you want to strip the unknown keys from the objects that you are validating.
cf options on https://github.com/hapijs/joi/blob/master/API.md#validatevalue-schema-options-callback
As in Version 14.3.4, there is a simple solution to this issue. Here is the code that solves the problem for you.
// Sample data for testing.
const user = {
fullname: "jayant malik",
email: "demo#mail.com",
password: "password111",
username: "hello",
name: "Hello"
};
// You define your schema here
const user_schema = joi
.object({
fullname: joi.string().min(4).max(30).trim(),
email: joi.string().email().required().min(10).max(50).trim(),
password: joi.string().min(6).max(20),
username: joi.string().min(5).max(20).alphanum().trim()
})
.options({ stripUnknown: true });
// You validate the object here.
const result = user_schema.validate(user);
// Here is your final result with unknown keys trimmed from object.
console.log("Object with trimmed keys: ", result.value);
const joi = require('joi');
joi.validate(object, schema, {stripUnknown:true}, callback);
Here is the current way to include the strip unknown option:
const validated = customSchema.validate(objForValidation, { stripUnknown: true });
If you pass in an objForValidation that has a key which isn't defined in your customSchema, it will remove that entry before validating.

Categories

Resources