update array of object of object MongoDB - node.js

I have this model
student: {
package:{
type: mongoose.Schema.Types.ObjectId,
ref: 'Package',
},
history: [
{
package: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Package',
},
orderDate: {
type: Date,
default: new Date().toLocaleDateString('id'),
},
Status: {
type: String,
default: 'Pending',
},
},
],
}
What I want to do is that I want to update Student.package and Student.history in 1 pass
I create this method in my model
StudentSchema.methods.updatePackage= function(idPackage) {
this.package = idPackage;
return this.save();
};
StudentSchema.methods.updateHistory= function(idPackage) {
this.history.push(idPackage);
return this.save();
};
and I'm trying to do something like this in my controller
buyPack: async (req, res, next) => {
try {
let dataStudent = await Student.findById('5b83443040e3751bb4e32a21');
await dataStudent.updatePackage(req.body);
await dataStudent.updateHistory(req.body);
return res.json(dataStudent);
} catch (err) {
console.log(err);
next(err);
}
},
I think the first and second methods are wrong, but I have tried to figure it out in almost half of day, but still no luck. What is the best way to achieve my goals?
Do I make my model wrong? or do the methods I created are wrong?

Mongoose model rename with plural .. and you refer with singular with "S", "Package" change it to "Packages"

Related

mongoose delete from array

I need to remove the user's id from all objects in the collection except the one that was passed, in my example it is value: 'Тата', tell me how to make such a request?
console.log(result)
[
{
_id: 5fa702b2f18e5723b4c00d9f,
value: 'Тата',
vote: { '36e7da32-f818-4771-bb5e-1807b2954b5f': [Array] },
date: 2020-11-07T20:25:22.611Z,
__v: 0
}
]
console.log(req.body)
{ value: 'Тата', habalkaId: '36e7da32-f818-4771-bb5e-1807b2954b5f' }
console.log(req.user._id)
5f63a251f17f1f38bc92bdab
that's all I could do, just find
router.post('/', passport.authenticate('jwt', {session: false}), (req, res) => {
FirstName.find({value: req.body.value})
.then(result => {
if (result.length) {
console.log(result)
console.log(req.body)
console.log(req.user._id)
FirstName.find({value: {$ne: 'Слоник'}}, function (err, arr) {
arr.map(e => {
if (e.vote[req.body.habalkaId].length) {
if(e.vote[req.body.habalkaId].includes(String(req.user._id))){
console.log(e.vote[req.body.habalkaId])
}
}
})
})
} else {
new FirstName({
value: req.body.value,
vote: {[req.body.habalkaId]: [String(req.user._id)]}
}).save();
}
})
// res.json({res: req.body})
})
FirstName.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Create Schema
const FirstNameSchema = new Schema({
value: {
type: String
},
vote: {
type: Object
},
date: {
type: Date,
default: Date.now
}
});
module.exports = FirstName = mongoose.model('firstname', FirstNameSchema);
If I've understand well, you want something like this:
db.collection.update({
"value": {
"$ne": "tata"
}
},
{
"$pull": {
"vote.array_name": "id_value"
}
},
{
multi: true
})
First of all, find all document that not match the value with the given one. Then, for each document found, delete the object from the array, using $pull where the id given matches.
Example here
Please check the payground and check if I've used the correct schema and it shows the expected output.

Expected 'property' to be of type string, instead found type object - Dynamoose

I am working with AWS DynamoDB and Dynamoose trying to fetch records using Scan function, but facing an issue that is not recognizable for me.
Stragenly, it's able to fetch records from another table in the same way and successfully get the records.
Here's my Code:
const vehicleMasterSchema = new dynamoose.Schema({
"id": String,
"customer_account_number": String,
"fuel_type": String,
"make": String,
"model": String,
"odometer_gatex": String,
"plate_no": String,
"rfid_gatex": String,
"sales_agreement_id": String,
"vehicle_category": String,
"vehicle_id": String,
}, {
"timestamps": {
"createdAt": "create_date",
"updatedAt": null // updatedAt will not be stored as part of the timestamp
}
});
const vehicleMasterModel = dynamoose.model("vehicle_master", vehicleMasterSchema, { "create": false });
router.post('/getFuelingStatus', (req, res) => {
var companyInfo = req.body;
try {
console.log(typeof vehicleMasterModel);
vehicleMasterModel.scan("customer_account_number").eq(companyInfo.customerId).exec((error, results) => {
if (error) {
console.error(error);
} else {
res.json(results);
}
});
} catch (error) {
res.json(error);
}
});
The TypeMismatch error is coming up only for this model same code is working for the other table.
Console Error
My Table
This appears to be related to this github issue on Dyanmoose
My guess is that the problem could be related with the name of your attribute, model.
In fact, this is the actual case: the following code, extracted from the source code in Document.ts is the one which is overwriting your model property:
Object.defineProperty(this, "model", {
"configurable": false,
"value": model
});
This is how the Document looks like before:
And after the execution of the aforementioned code:
This code is executed when processing the Scan exec function in DocumentRetriever.ts when the library maps every Item returned by DynamoDB to their internal Document representation, exactly in this line of code:
const array: any = (await Promise.all(result.Items.map(async (item) => await new this.internalSettings.model.Document(item, {"type": "fromDynamo"}).conformToSchema({"customTypesDynamo": true, "checkExpiredItem": true, "saveUnknown": true, "modifiers": ["get"], "type": "fromDynamo"})))).filter((a) => Boolean(a));
The error you reported is a consequence of that change when the type of the returned Item is checked against your schema model in the checkTypeFunction:
const {isValidType, matchedTypeDetails, typeDetailsArray} = utils.dynamoose.getValueTypeCheckResult(schema, value, genericKey, settings, {"standardKey": true, typeIndexOptionMap});
if (!isValidType) {
throw new Error.TypeMismatch(`Expected ${key} to be of type ${typeDetailsArray.map((detail) => detail.dynamicName ? detail.dynamicName() : detail.name.toLowerCase()).join(", ")}, instead found type ${typeof value}.`);
...
Please, try a different name, I think it will work properly.
Schema must be like this :
const ImageGalleryFoldersSchema = new Schema({
key: {
type: String,
hashKey: true,
required: true,
},
displayName: {
type: String,
required: true,
},
parentFolderKey: {
type: String,
required: false,
},
isActive: {
type: Boolean,
default: true,
required: false,
},
}, {
timestamps: true,
});
Maybe your problem is caused due to asynchronous behaviour.
To be more specific, I think that by the time you call the "scan"-function-chain the body-request has not been finished. However, due to the nature of Hoisting, the object "companyInfo" was already being initialised before you enter the function-call.
Therefore, you may get the specified "TypeMismatch"-error.
Could you please try implementing the following async/await-structure and tell me if this helps:
router.post('/getFuelingStatus', async (req, res) => {
var companyInfo = await req.body;
try {
console.log(typeof vehicleMasterModel);
vehicleMasterModel.scan("customer_account_number").eq(companyInfo.customerId).exec((error, results) => {
if (error) {
console.error(error);
} else {
res.json(results);
}
});
} catch (error) {
res.json(error);
}
});

MongoError: The positional operator did not find the match needed from the query. at Function.create()

I am trying to update values into an object array(users) if it does not already exist in MongoDB. Here is my Schema:
ownerid:{
type: Number,
required: 'This field is required'
},
name:{
type: String
},
capacity:{
type: Number
},
basePrice:{
type: Number
},
users:[{
id: Number,
price: Number,
target: Number,
frequency: Number
}],
filePath:{
type: String
},
status:{
type: String
}
});
The following is my router method:
app.post('/userBid',urlEncodedParser,function(req,res){
resName=req.body.resName;
console.log(resName);
Resource.find({"name":resName},{"users.id": userid},function(err,existingUser){
if (!existingUser){
console.log("already in queue");
//res.render('userHome.ejs');
}
else{
console.log("in update");
Resource.update({'name': resName},
{'$set': {
'users.$.frequency': 1,
'users.$.id': userid,
'users.$.price': req.body.price,
'users.$.target': req.body.target
}},{'multi': true},
function(err,model) {
if(err){
console.log(err);
return res.send(err);
}
return res.json(model);
});
}
});
});
I have tried using $push but that does not seem to work either. Also I can't use '0' instead of '$' as multiple users will be inserted by the users and I need to store them all.
Issue :
Reason why we use $ is to update a specific object/few specific objects in an array field that meet our condition. So when you use any positional operators like $ or $[] then in filter part of .update({filterPart},{updatePart}) query you need to use a filter to find specific object in array. So for example if id field is unique in users array then you can use it to filter/find the object needs to be updated.
Try this below code :
app.post("/userBid", urlEncodedParser, function (req, res) {
resName = req.body.resName;
console.log(resName);
/** Use findOne if `name` is unique.
* Cause `existingUser` will be array, instead findOne will return an object or null - So you can just do if(existingUser)to check true values */
Resource.find({ name: resName }, { "users.id": userid }, function (
err,
existingUser
) {
if (!existingUser) {
console.log("already in queue");
//res.render('userHome.ejs');
} else {
console.log("in update");
Resource.update(
{ name: resName, "users.id": userid }, /** `"users.id": userid` is the only change needed */
{
$set: {
"users.$.frequency": 1,
"users.$.id": userid,
"users.$.price": req.body.price,
"users.$.target": req.body.target,
},
},
{ multi: true },
function (err, model) {
if (err) {
console.log(err);
return res.send(err);
}
return res.json(model);
}
);
}
});
});

Mongoose reports no error on updating, but does not update

losing my mind here for something for a MongoDB document update with Mongoose, not reporting any error but not actually updating successfully.
I have this schema:
/**
* Branch Schema
*/
let BranchSchema = new Schema({
name: String,
domain: String,
email: String,
bm: { type: Schema.ObjectId, ref: 'User' },
st: [{ type: Schema.ObjectId, ref: 'User' }],
stockCurrent: {
paper: Schema.Types.Object,
ink: Schema.Types.Object
},
stockNeeded: {
paper: Schema.Types.Object,
ink: Schema.Types.Object
},
}, { versionKey: false, usePushEach: true });
mongoose.model('Branch', BranchSchema);
Trying to update stockCurrent, using this logic:
Branch.findById(config.branch.id, function (err, branch) {
if (err) {
res.status(422).send({
message: 'הסניף לא נמצא'
});
} else {
console.log(branch);
Object.keys(req.body.stock).forEach(function (type) {
Object.keys(req.body.stock[type]).forEach(function (code) {
if (req.body.stock[type][code] > 0) {
if (typeof branch.stockCurrent[type][code] === 'undefined') {
branch.stockCurrent[type][code] = 0;
}
branch.stockCurrent[type][code] += req.body.stock[type][code];
}
});
});
console.log(branch);
branch.save(function (err, updated) {
console.log("err: " + err);
if (err) {
stock.remove();
res.status(422).send({
message: 'שגיאה בשמירת מלאי'
});
} else {
console.log(updated);
res.send({
message: 'מלאי נוסף בהצלחה'
});
}
});
}
});
I get to to success part, having my console log this:
{
"_id":5dd276a6bcc29a13789fcecb,
"name":"בצלאל ארכיטקטורה",
"domain":"bezalel.eazix.io",
"email":"eazix.1.bezalel#gmail.com",
"bm":5cdd2130d192ea03a87d2dfd,
"stockNeeded":{
"ink":{
"GY":2,
"PM":2,
"M":2,
"MBK":2,
"PBK":2,
"PC":2,
"Y":2,
"C":2,
"waste":2
},
"paper":{
"COATED":5,
"PLAIN":5,
"PHOTO":3
}
},
"stockCurrent":{
"paper":{
"PLAIN":0
},
"ink":{
"waste":0
}
},
"st":[
]
}{
"_id":5dd276a6bcc29a13789fcecb,
"name":"בצלאל ארכיטקטורה",
"domain":"bezalel.eazix.io",
"email":"eazix.1.bezalel#gmail.com",
"bm":5cdd2130d192ea03a87d2dfd,
"stockNeeded":{
"ink":{
"GY":2,
"PM":2,
"M":2,
"MBK":2,
"PBK":2,
"PC":2,
"Y":2,
"C":2,
"waste":2
},
"paper":{
"COATED":5,
"PLAIN":5,
"PHOTO":3
}
},
"stockCurrent":{
"paper":{
"COATED":1,
"PHOTO":2,
"PLAIN":0
},
"ink":{
"PM":1,
"waste":0
}
},
"st":[
]
}**"err":null**{
"_id":5dd276a6bcc29a13789fcecb,
"name":"בצלאל ארכיטקטורה",
"domain":"bezalel.eazix.io",
"email":"eazix.1.bezalel#gmail.com",
"bm":5cdd2130d192ea03a87d2dfd,
"stockNeeded":{
"ink":{
"GY":2,
"PM":2,
"M":2,
"MBK":2,
"PBK":2,
"PC":2,
"Y":2,
"C":2,
"waste":2
},
"paper":{
"COATED":5,
"PLAIN":5,
"PHOTO":3
}
},
"stockCurrent":{
"paper":{
"COATED":1,
"PHOTO":2,
"PLAIN":0
},
"ink":{
"PM":1,
"waste":0
}
},
"st":[
]
}
I can see the here the initial state, the updated version before saving, and the the err:null, and the allegedly updated document.
but alas! the document wasn't really updated. it remains the same.
I have tried many things, searching and looking for similar cases, checking my schema, adding useStrict:false to the schema, nothing helps.
Mongoose ver 4.13.20, Mongodb ver 3.6.17
SOS
Dor
I'm guessing the SchemaTypes are the problem? In Mongoose 4.x, these are the only valid SchemaTypes:
String
Number
Date
Buffer
Boolean
Mixed
Objectid
Array
Notice that Mixed is an option but not Object. You need to tell Mongoose that you updated a Mixed field using model.markModified('pathName'). See the Mixed docs.
So in your case, the code below may fix the issue:
branch.markModified('stockCurrent');
branch.save(function (err, updated) {
// ...

How do i $set and $push in one update MongoDB?

I'm trying to $push and $set at the same time, $push is working just fine, when it comes to $set, it generates this error:
MongoError: The positional operator did not find the match needed from
the query. Unexpanded update: files.$.name
Here's the code
Course.update(
{
_id: req.body.courseId,
'files.fileUrl': { $ne: url }
},{
$push: { files: { fileUrl: url } },
$set: {'files.$.name': file.name},
}, function(err, count) {
if (err) return next(err);
console.log("Successfully saved")
});
and the ORM model, I'm using mongoose
var CourseSchema = new Schema({
files: [{
fileUrl: String,
name: { type: String, default: 'File name'}
}]
});
Any help would be appreciated. Thanks.
As the error states looks like the query used is returning no documents or returning documents having no files[].
Another reason for which it might be throwing error is that you're trying to $push & $set in the same field files and probably running into an issue similar to https://jira.mongodb.org/browse/SERVER-1050
IMHO, there is no good reason to use the same field in $push & $set, instead you can simply change
$push: { files: { fileUrl: url } },
$set: {'files.$.name': file.name},
to
$push: { files: { fileUrl: url, name: file.name } },
I have written similar kind of query for my project
Hope u could relative this to your scenario
exports.candidateRating = function(req, res) {
console.log(req.query);
console.log(req.body.RoundWiseRatings);
Profiles.update({
"name": req.query.name
}, {
$set: {
"ratings": req.body.ratings,
},
$push: {
"RoundWiseRatings": req.body.RoundWiseRatings
}
}, {
multi: true
}, function(error, profiles) {
if (error) {
}
return Profiles.find({
name: req.query.name
}, function(err, profiless) {
console.log(profiless);
if (err) {
return handleError(res, err);
}
return res.status(200).json(fnStruncturedData(profiless[0].RoundWiseRatings));
});
});};
And this worked for me :)

Resources