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
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.
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) ]}
},
})
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()
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);
});
};
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'
]