nodejs objects property can only be changed to int and not string - javascript

i just got this wierd issue in which the code below returns the refno for all Object in the array as expected But
let records = await Expense.find({}).exec(); // records is an array of objects [{},{}]
for (let obj of records) { // the obj has a refno property which i want to change
obj.refno = 0 // this works as expected by changing refno property to 0
}
console.log(records)
this code of code below of chaning the properties value to string Does not work
for (let obj of records) {
obj.refno = "QM"+obj.refno
}
console.log(records) // IN this the refno. doesnt change
my requirment is to change the refno to a string
//the object
{
_id: 5efed2c813b03d331e4dc052,
refno: 102,
project: 'EV Battery Pack',
invoiceno: 'dia',
description: 'black frame',
date: '2020-07-03',
}
so chaning the property to other number works but not to string , i cant get how this happens or am i missing something ?, anyways i got around this by declaring another property and storing the string in it but I dont know why the int cant be changed to string inside object
can some one explain why this happens
thanks for help
Edit : schema of expense
var schema = new Schema({
refno: { type: Number, require: true },
project: { type: String, require: true },
projectid: { type: Number, require: true },
invoiceno: { type: String, require: true },
description: { type: String, require: true },
date: { type: String, require: true },
INR: { type: Number, require: true },
USD: { type: Number, require: true },
remarks: { type: String, require: true },
});

The result of your .find().exec() call are mongoose documents which do not allow to modify their values if the resulting datatype is not compliant with the schema-constraints.
However, you can use .lean() (see https://mongoosejs.com/docs/api.html#query_Query-lean) on the mongoose document which will convert it to a plain js-object which you then can modify arbitrarily:
let records = await Expense.find({}).exec().lean();

Related

Mongoose findByIdAndUpdate method not incrementing document value

I am trying to update the like count of job posts in my application using the $inc operator and the findByIdAndUpdate method from Mongoose. The correct document is being retrieved and returned but the like count for the job post never moves up from 0 and no updates are performed in the database collection.
Below is the code I am currently using to perform the update.
Jobs.findByIdAndUpdate(req.params._id , { $inc: {likes: 1}} , {new: true})
.then((ret) => {
res.send(ret)
})
Job schema
const mongoose = require('mongoose');
let JobSchema = mongoose.Schema({
student_name: {
type: String,
required: true
},
subject: {
type: String,
required: true
},
grade: {
type: Number,
required: true
},
area: {
type: String,
required: true
},
desc: {
type: String,
required: true
},
accepted: {
type: Boolean,
required: true,
default: false
},
tutor_name: {
type: String,
required: false
},
} , {collection: 'jobs'});
let Job = mongoose.model('Job' , JobSchema);
module.exports = Job;
Any insight into what is preventing the update from performing would be greatly appreciated
I have tried using two queries, one to retrieve the current likes of a post and another to manually update the doc with the incremented value. I have tried nesting the queries using .then() statements and have also tried the updateOne() and findOneAndUpdate() methods as alternatives. I have tried experimenting with the $set and $inc operators in my queries to see if either of them perform the changes, but neither do.
I am expecting the incremented 'likes' value to be reflected in the database and for the updated job document to be returned and echoed back to the console.
Your schema is missing a likes field, which means Mongoose will remove it from queries/updates (since it doesn't match the schema). Make sure to add it:
likes: {
type: Number,
default: 0
}
Can you try something like this (adding [] around update):
Jobs.findByIdAndUpdate(req.params._id , [{ $inc: {likes: 1}}] , {new: true})
.then((ret) => {
res.send(ret)
})
EDITED:
Jobs.findByIdAndUpdate(req.params._id , [{ $set: {likes: "$likes"+1}}] , {new: true})
.then((ret) => {
res.send(ret)
})

document not filtered by property

My document item looks like that:
I'm trying to filter the document by year like that:
async function getBooksByYear(year: number): Promise<Book[]> {
return BookModel.find({'year': year})
}
I send the request from postman: http://localhost:4000/api/books?year=1990
but it's not working - it's returning the entire document items
appreciate any help
The answer is: this property wasn't declared in the schema.
when I add the year to the schema:
export const BookSchema = new mongoose.Schema<Book>({
author: {
type: String,
required: [true, "missing author name"]
},
country: {
type: String,
required: [true, "missing country"]
},
// I add this part now
year: {
type: Number
}
})
it works :)

How to pass schema type: Object's key rules

I am trying to understand how to validate, an object using Meteor-Collection2. I can better explain in the code below:
// This is the object structure to validate
// const obj = {
// name: 'Test',
// active: true,
// }
Test.schemaObj = {
someOtherName: {
type: String, // Not the same as obj variable
},
testType: {
type: Object,
// The goal is to define rules for validation for
// things that this will contain.
},
// Inside the object: {
// type: String,
// required: true,
//},
// Inside the object: {
// type: Boolean,
// required: true,
//},
};
I understand that required is automatically set to true when not defined.
My purpose is to basically list all the keys that the object must have and their validation rules. I know how an array of object works, I am just not sure what the syntax is for object validation.
I went through the documentation and stack-overflow, but I was not able to find it anywhere online explicitly showing the syntax.
I am sure that I am missing something basic however, being new to this I was hoping that someone can help me.
I understood which you want to validate the testType object. Then there are two ways:
You can add the blackbox: true, this will allow that object have any structure;
You need to define each property of object, like this:
Test.schemaObj = {
someOtherName: {
type: String, // Not the same as obj variable
},
testType: {
type: Object,
// The goal is to define rules for validation for
// things that this will contain.
},
"testType.attribute1": {
type: String,
required: true,
},
"testType.attribute2": {
type: Boolean,
required: true,
},
};

Mongoose update nested object in array of record

I am currently having a problem where I am trying to update an of a nested array in a Mongoose record.My schema is as follows:
const customerSchema = new mongoose.Schema({
kimCustomerId: {
type: Number,
required: true
},
addresses: [
{
created: Date,
updated: Date,
addressInfo: {
type: { type: String },
typeOfAddress: String,
careOf: String,
address: String,
addressRow1: String,
addressRow2: String,
zipcode: String,
city: String,
countryCode: String,
physicalAddressType: String,
validFrom: Date,
validTo: Date
}
}
],
.....
As you can see, the adrress array for each record holds many addresses. I want to be able to pass through an update object and update the properties inside the addressInfo nested object inside a particular array object. Here is my query as it stands:
const updated = await db.models.customers.findOneAndUpdate(
{
_id: customer._id,
'addresses.addressId': addressData.addressId
},
{ $set: { 'addresses.$': addressData } },
{ new: true }
);
and an example of an object I pass through to update a record:
{
addressId: officialAddressExists.addressId,
addressInfo: {
validTo: new Date().toISOString()
}
}
What I want to happen is, when I pass this object to the schema method, I want to select the correct address by the values 'kimCustomerId' and 'addressId' (which I have working fine) then only update the values of the 'addressInfo' nested object that I have passed and keep the ones not passed as they are, in this case the 'validTo' field but it can be any number of them updated. It is overwriting the whole 'addressInfo' nestedObject at the moment so I presume I have to do some kind of set operation on that nested object as well but I am unsure how.
Is anyone able to point me in the right direction here?
Thanks!
There is no straight way to do this in query, you can do it in your client side, something like,
// Sample body request
let addressData = {
addressId: 1,
addressInfo: {
validTo: new Date().toISOString(),
typeOfAddress: "Home",
address: "ABC"
}
};
let set = {};
for (let key in addressData.addressInfo) {
set["addresses.$.addressInfo." + key] = addressData.addressInfo[key];
}
console.log(set);
Pass set variable in to your query,
const updated = await db.models.customers.findOneAndUpdate(
{
_id: customer._id,
'addresses.addressId': addressData.addressId
},
{ $set: set },
{ new: true }
);

Check for not required property existing in mongoose model variable

So, I have this mongoose scheemas structure:
const execStatusScheema = new mongoose.Schema(...)
const notifyScheema = new mongoose.Schema({
...
sms: {
type: Boolean,
required: true
},
smsStatus: {
type: execStatusScheema
},
telegram: {
type: Boolean,
required: true
},
telegramStatus: {
type: execStatusScheema
},
voice: {
type: Boolean,
required: true
},
voiceStatus: {
type: execStatusScheema
}
})
const Notify = mongoose.model('Notify', notifyScheema)
module.exports.Notify = Notify
as you can see in Notify scheema smsStatus, voiceStatus and telegramStatus are not required. If sms is false, the smsStatus property is not assiged in my code, and for voice and telegram the same behavior. I want to check in Notify some of these propertys. I do the follow:
const uncomplitedNotifies = await Notify.find(...).select('smsStatus voiceStatus telegramStatus sms voice telegram')
uncomplitedNotifies.forEach(async notify => {
console.log(notify)
if ('telegramStatus' in notify) {
console.log('123')
}
...
Result is:
{ _id: 5ba07aaa1f9dbf732d6cbcdb,
priority: 5,
sms: true,
telegram: false,
voice: false,
smsStatus:
{ status: 'run',
_id: 5ba07aaa1f9dbf732d6cbcdc,
errMessage: 'Authentication failed',
statusDate: '2018-9-18 12:10:19' } }
123
Ok, I find one, and its ok, but my if statment is true even I have no this property in my object. I guess it check in scheema object, where its declared, but I want to check in my 'real' object I got by query.
I also try this checking case, but the same result:
if (typeof something === "undefined") {
alert("something is undefined");
}
How can I check this object correctly ?
The in operator checks the object's own properties and its prototype chain. The unset properties are in the prototype chain of your object, but not on the object's own properties:
const hasTelegramStatus = 'telegramStatus' in document; // true
const hasTelegramStatus = document.hasOwnProperty('telegramStatus') // false
One option is to convert the query into an object by doing document.toObject(), which will remove the prototype chain and only return the own properties.

Categories

Resources