Mongoose - express server update specific index in array of objects - node.js

I've created a custom identifier ID and I'm trying to update my coins and aswell as the first
array object purchased bool to true.
this is how my data looks like
[
{
"identifier": "123456789",
"coins": 100,
"equipments": [
{
"item": "itemname",
"price": 100,
"gold": 10,
"level": 1,
"condition": 100,
"purchased": false
},
{
"item": "itemname2",
"price": 80,
"gold": 8,
"level": 1,
"condition": 100,
"purchased": false
},
],
"__v": 0
}
]
This is my update routes
router.put("/update/:identifier", function(req,res){
User.find({identifier: req.params.identifier}, function(err, equipment) {
equipment.coins= 50;
equipment[0].equipments.purchased = true;
equipment[0].save(function (err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(equipment);
}
});
});
});
When I run it nothing happens and it doesn't give any errors

This is not the conventional approach.
You need to do it like this.
router.put("/update/:identifier", function(req,res){
User.findOne({identifier: req.params.identifier}, function(err, equipment) {
equipment.coins= 50;
equipment.equipments.purchased = true;
equipment.save(function (err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(equipment);
}
});
});
});
BONUS:I would suggest you to use findAndUpdateOne()

Related

How to pull out object heading from an array

I have a JSON response structure like this
{
"_id": "620e97d76ca392a43097cca6",
"user": "620295cbd67ece90802d2522",
"orderId": "EnrL7C",
"Items": [
{
"product": {
"name": "Fresh Salad",
"id": "61f2911723ff35136c98ad3e"
},
"quantity": 1,
"price": 1250,
"_id": "620e97d76ca392a43097cca7"
},
],
}
But i want the product not to be an object, so it should look like this
{
"_id": "620e97d76ca392a43097cca6",
"user": "620295cbd67ece90802d2522",
"orderId": "EnrL7C",
"Items": [
{
"name": "Fresh Salad",
"id": "61f2911723ff35136c98ad3e",
"quantity": 1,
"price": 1250,
"_id": "620e97d76ca392a43097cca7"
},
],
}
This is my code responsible for the response output
exports.getOrder = (req,res) => {
Order.findOne({orderId: 'EnrL7C'})
.populate("Items.product", "name")
.exec((error, order) => {
if(error) return res.status(400).json({ error });
if (order) {
return res.json(order);
}else{
return res.json(['No order found']);
}
});
Sometimes when I'm too lazy to look up all the mongoose documentation and figure out what version I'm on etc, I use the .lean() to just convert it to a normal JS object, which I'm way more comfortable with.
exports.getOrder = (req, res) => {
Order.findOne({ orderId: "EnrL7C" })
.lean() // add lean
.populate("Items.product", "name")
.exec((error, order) => {
if (error) return res.status(400).json({ error });
if (order) {
// fix the structure in javascript
order.Items = order.Items.map((item) => {
const flat = {
...item.product,
...item,
};
delete flat.product;
return flat;
});
return res.json(order);
} else {
return res.json(["No order found"]);
}
});
};
Let me know if that doesn't work, so I can update the answer.

sequelize Mysql data two between date all record show but some ... findall REST API ......simple problems

This my API Code .it work perfectly but missing my "startedDate":"2022-01-01", and
"endDate":"2022-01-31" … how I write the the function pls solved my problem and share your idea..
async getcurrentmonthorder2(req, res, next) {
try {
const {startedDate ,endDate} = req.body;
db.product.findAll({
attributes:[[sequelize.fn('sum',sequelize.col('profit_total')),'total']],
where : {"createdAt" : {[Op.between] : [new Date(startedDate).setHours(0,0,0,0) , new Date(endDate).setHours(23,59,59,999) ]}},
})
.then(list => {
res.status(200).json({ 'success': true, data: list });
})
.catch(function (err) {
next(err)
});
}
catch (err) {
res.status(500).json({ 'errors': "" + err });
}
}
#I have got output from postman..
{
"success": true,
"data": [
{
"total": "121",
}
]
}
#but I want to this output pls help share your idea
{
"success": true,
"data": [
{
"total": "121",
"startedDate":"2022-01-01",
"endDate":"2022-01-31"
}
]
}
my data
{id: 1, total: 20, profit_total: 15, createdAt: "2021-12-30T15:59:10.000Z",…}
Your problem comes from the attributes which you indicated in your query: You told SEQUELIZE to return only TOTAL. I suggest you this::
db.product.findAll({
attributes:[[sequelize.fn('sum',sequelize.col('profit_total')),'total'], 'startedDate', 'endDate'],
where : {
"createdAt" : {
[Op.between] : [new Date(startedDate).setHours(0,0,0,0), new Date(endDate).setHours(23,59,59,999) ]}
},
})

Traversing array and changing object values

I'm trying to update the values ​​of my payments array objects
{
"balance": 109610,
"gifts": [],
"orders": [],
"payments": [{
"isPaid": 0,
"status": "Pending",
"address": "3KsdQbmADyz1KNN7qqX1yZcMXBbfFCm31r",
"date": 1624057559970
}, {
"isPaid": 0,
"status": "Pending",
"address": "3FYQK6YiAaL8fEbDWaXYw38CJN3K2y5dPD",
"date": 1624058531601
}],
"isVendedor": false,
"isAdmin": true,
"createdAt": {
"$date": "2021-06-17T21:10:15.020Z"
},
"username": "teste",
"email": "teste#teste.com",
"password": "$2a$10$qUNkorDuvbf.AYLTvjNc4ebKyNgLa7L9NoTBwAIV8.BfN51umaD9O",
"__v": 3
}
First, I look for the object of the user who made a request to my server
const userPayment = await User.find({"payments.address": notification.address}).exec();
Then I go through the user object and find it until I find the position where I find notification.address again
userPayment.forEach((AllPayments, index) => {
AllPayments.payments.forEach((payment, index) => {
if (payment.address == notification.address) {
if (payment.isPaid || payment.status != "Pending")
return res.json({
success: false,
error: "Payment Already Processed!",
});
const valueToDeposit = Math.round(notification.fiat_amount);
console.log(
userPayment[0].payments[index].isPaid,
userPayment[0].payments[index].status
);
// Set payments[index].isPaid = true
// Set payments[index].status = "Paid"
});
});
So I tried to make these 3 ways and none of them was successful.
userPayment[0].balance += valueToDeposit; // this works when save() is triggered
userPayment[0].payments[index].isPaid = 1; // this doesnt works when save() is triggered
userPayment[0].payments[index].status = "Paid"; // this doesnt works when save() is triggered
userPayment[0].updateOne({"payments.address": notification.address}, { $set: { "payments.$.isPaid": 1,"payments.$.status":"Paid" } },(err, result) => { console.log(err, result); }); this doesnt works
userPayment[0].save()

How to speed up node service

I have two collections categorytypes and categories, each category type has multiple categories. When I am fetching all category details in each index of category there should be a a filed of category_type giving all details of category_type.
My code is:
exports.findAllWithParentChild = (req, res) => {
let resData = [];
Models.Category.find()
.then(data => {
var results = [];
async.each(data,function(cat,callback) {
console.log(cat.categorytype_id)
Models.CategoryType.findOne({'_id' : mongoose.Types.ObjectId(cat.categorytype_id)},function(err,catType) {
var obj = cat.toObject();
obj.category_type = catType;
results.push(obj);
callback(err);
});
},
function(err) {
if (err) throw err;
res.send({
response: true,
message: "Category deleted successfully.",
data : results
});
});
});
};
And the format I need in response:
{
"_id": "5cb78c44ede6452278d13fbe",
"title": "fhhghgf",
"description": "hgfhgf",
"slug": "hgfhgfhgf",
"categorytype_id": "5cb78ba8ede6452278d13fb6",
"user_id": "hgfhgfh",
"status": true,
"created_at": "2019-04-17T20:27:48.821Z",
"updated_at": "2019-04-17T20:27:48.821Z",
"__v": 0,
"category_type": {
"_id": "5cb78ba8ede6452278d13fb6",
"title": "asde",
"description": "asde",
"slug": "asde",
"user_id": "asde",
"status": true,
"created_at": "2019-04-17T20:25:12.863Z",
"updated_at": "2019-04-17T20:25:12.863Z",
"__v": 0
}
},
Is there any better way? Thanks for your assistance.
Change your code with below one and check the output
exports.findAllWithParentChild = (req, res) => {
Models.Category.find({}).
populate('categorytypes').
exec(function (err, data) {
if (err) return handleError(err);
console.log('Success', data);
});
};

Using pull in mongoose model

Should this work? I am trying to remove a single subdocument (following) from a document (this) in the UserSchema model.
UserSchema.methods.unFollow = function( id ) {
var user = this
return Q.Promise( function ( resolve, reject, notify ) {
var unFollow = user.following.pull( { 'user': id } )
console.log( unFollow )
user.save( function ( error, result ) {
resolve( result )
})
})
}
These are the schemas:
var Follows = new mongoose.Schema({
user: String,
added: Number
})
var UserSchema = new mongoose.Schema({
username: {
type: String,
required: true,
unique: true
},
following: [ Follows ]
})
user-controller.js
/*
Unfollow user.
*/
exports.unFollow = function ( req, res ) {
User.findOne( { token: req.token }, function ( error, user ) {
user.unfollow( req.body.id )
.onResolve( function ( err, result ) {
if ( err || !result ) return res.status( 500 ).json( "User could not be unfollowed." )
return res.status( 200 ).json( "User unfollowed." )
})
})
}
user-model.js
/*
Unfollow a user.
*/
UserSchema.method( 'unfollow', function unfollow ( id ) {
this.following.pull( { user: id } )
return this.save()
})
You generally assign methods using the method function:
UserSchema.method('unFollow', function unFollow(id) {
var user = this;
user.following.pull({_id: id});
// Returns a promise in Mongoose 4.X
return user.save();
});
Also, as noted, you don't need to use Q as save will return a mongoose promise.
UPDATE: Mongoose's array pull method will work with matching primitive values but with subdocument objects it will only match on _id.
UPDATE #2: I just noticed your updated question shows that your controller is doing a lookup first, modifying the returned document and then saving the document back to the server. Why not create a static rather than a method to do what you want? This has the added bonus of being a single call to the DB rather than two per operation.
Example:
UserSchema.static('unfollow', function unfollow(token, id, cb) {
var User = this;
// Returns a promise in Mongoose 4.X
// or call cb if provided
return User.findOneAndUpdate({token: token}, {$pull: {follows: {user: id}}}, {new: true}).exec(cb);
});
User.unfollow(req.token, req.body.id).onResolve(function (err, result) {
if (err || !result) { return res.status(500).json({msg: 'User could not be unfollowed.'}); }
return res.status(200).json({msg: 'User unfollowed.'})
});
Bonus follow static:
UserSchema.static('follow', function follow(token, id, cb) {
var User = this;
// Returns a promise in Mongoose 4.X
// or call cb if provided
return User.findOneAndUpdate({token: token}, {$push: {follows: {user: id}}}, {new: true}).exec(cb);
});
User.follow(req.token, req.body.id).onResolve(function (err, result) {
if (err || !result) { return res.status(500).json({msg: 'User could not be followed.'}); }
return res.status(200).json({msg: 'User followed.'})
});
NOTE: Used in "mongoose": "^5.12.13".
As for today June 22nd, 2021, you can use $in and $pull mongodb operators to remove items from an array of documents :
Parent Document :
{
"name": "June Grocery",
"description": "Some description",
"createdDate": "2021-06-09T20:17:29.029Z",
"_id": "60c5f64f0041190ad312b419",
"items": [],
"budget": 1500,
"owner": "60a97ea7c4d629866c1d99d1",
}
Documents in Items array :
{
"category": "Fruits",
"bought": false,
"id": "60ada26be8bdbf195887acc1",
"name": "Kiwi",
"price": 0,
"quantity": 1
},
{
"category": "Toiletry",
"bought": false,
"id": "60b92dd67ae0934c8dfce126",
"name": "Toilet Paper",
"price": 0,
"quantity": 1
},
{
"category": "Toiletry",
"bought": false,
"id": "60b92fe97ae0934c8dfce127",
"name": "Toothpaste",
"price": 0,
"quantity": 1
},
{
"category": "Toiletry",
"bought": false,
"id": "60b92ffb7ae0934c8dfce128",
"name": "Mouthwash",
"price": 0,
"quantity": 1
},
{
"category": "Toiletry",
"bought": false,
"id": "60b931fa7ae0934c8dfce12d",
"name": "Body Soap",
"price": 0,
"quantity": 1
},
{
"category": "Fruit",
"bought": false,
"id": "60b9300c7ae0934c8dfce129",
"name": "Banana",
"price": 0,
"quantity": 1
},
{
"category": "Vegetable",
"bought": false,
"id": "60b930347ae0934c8dfce12a",
"name": "Sombe",
"price": 0,
"quantity": 1
},
Query :
MyModel.updateMany(
{ _id: yourDocumentId },
{ $pull: { items: { id: { $in: itemIds } } } },
{ multi: true }
);
Note: ItemIds is an array of ObjectId. See below :
[
'60ada26be8bdbf195887acc1',
'60b930347ae0934c8dfce12a',
'60b9300c7ae0934c8dfce129'
]

Resources