Count number documents from collection inside Array - javascript

I'm trying to count the number of documents inside an array from a collection.
Below you can see the Schema.
MongoDB Schema
What I want to count is each type of expenseType but since I have this value inside an array I don't know how to build a query to get this value.
The final result should be:
Water: 2 | Wifi: 1
And when I add new Water should be Water:3 and so on.
Below I show what I'm trying to do, but received an error
router.get("/getExpense", ensureAuthenticated, (req, res) => {
House.aggregate(
{
$match: {
userID: req.user.id,
expensesHouse: { $elemMatch: { status: "Public" } }
}
}
{ $group: { _id: "$Water", price: { $sum: 1 } } }
).then(house => {
console.log(res.json({ house }));
});
});
The res.json is because I send a JSON with the values and fetching to build a chart.
This is the fetch I'm doing.
getData();
async function getData() {
const res = await fetch("/houses/getExpense", {
headers: {
"Content-Type": "application/json",
Accept: "application/json"
}
})
.then(res => res.json())
.then(data => {
console.log(data);
});
}

You're looking for $unwind. It creates intermediary entries that you can group on.
House.aggregate(
{
$match: {
userID: req.user.id,
expensesHouse: { $elemMatch: { status: "Public" } }
}
},
{
$unwind: '$expensesHouse',
},
{ $group: { _id: "$expensesHouse.expenseType", price: { $sum: 1 } } }
).then(house => {
console.log(res.json({ house }));
});
I've also fixed the last group id.

Related

Update a nested array in a nested array

I am trying to update using this route.
router.put("/:id", async(req,res)=>{
try {
const updateUser = await User.findByIdAndUpdate(req.params.id, {
$push: {
clients:{
client_name: req.body.client_name,
client_Username: req.body.client_Username,
client_Password: req.body.client_Password,
documents : [
{
name : req.body.docName,
descritption : req.body.docDescription,
doc_upload : req.body.doc_upload,
}
]
}
}
},{new:true})
res.status(200).json(updateUser);
}
catch(err) {
res.status(500).json(err);
}
});
Once the function founds the id it updates client_name, client_Username and client_password without any issue.
My problem is when I try to update the nested array documents with a name/description and doc_upload. I am not able to do that.
What’s wrong ? How to do it please ?
One solution could be to separate the updates:
router.put('/:id', async (req, res) => {
try {
const { id } = req.params;
const { client_name, client_Username, client_Password } = req.body;
const updateUser = await User.findByIdAndUpdate(
id,
{
$push: {
clients: {
client_name,
client_Username,
client_Password,
},
},
},
{ new: true }
);
await User.findOneAndUpdate(
{
id,
'clients.client_name': client_name,
'clients.client_Username': client_Username,
},
{
$push: {
'clients.$.documents': {
name: req.body.docName,
descritption: req.body.docDescription,
doc_upload: req.body.doc_upload,
},
},
}
);
res.status(200).json(updateUser);
} catch (err) {
res.status(500).json(err);
}
});

How to create function edit objects in object array in Node.js

I want to create a patch or put a function for edit values of the object array.
comments: [{
body: String,
date: Date,
id: String
}],
router.put('/comment/:id', (req, res) => {
const commentbody = req.body.body
Blog.findOneAndUpdate({ "_id": req.params.id }, { $set: { comments: { body: commentbody } } }).then(result => {
res.send('comment edited');
})
.catch(err => res.send(err))
})

edit the last inserted record in mongodb

I am inserting two different objects into the db, i am doing this according to a certain criteria.
After that i am editing this record and setting the status to verified or not verified according to an amazon reply.
The problem is , i want to update the record that has been just inserted , since i am using findOneAndUpdate, only one record is being edited and it is not the last one it is the first.
Since the user can do as many purchases as he wants , he can have as many records as he want but only the first object found in the db having the userId sent as a param is edited.
what shall i use? the date and time when the object is inserted or what ?
async createAndSendToAmazon(data) {
try {
const records = new this.model(data);
const purchaseFromAppObjectRecord = await records.save();
let userId = purchaseFromAppObjectRecord.UserData[0].userId;
let receiptId = purchaseFromAppObjectRecord.receiptId;
await sendToAmazon(userId, receiptId);
await changeStatusToVerified(userId);
return purchaseFromAppObjectRecord;
} catch (error) {
return error;
}
}
}
async function sendToAmazon(userId, receiptId) {
const requestUrl = `https://appstore-sdk.amazon.com/version/1.0/verifyReceiptId/developer/2:smXBjZkWCxDMSBvQ8HBGsUS1PK3jvVc8tuTjLNfPHfYAga6WaDzXJPoWpfemXaHg:iEzHzPjJ-XwRdZ4b4e7Hxw==/user/${userId}/receiptId/${receiptId}`;
console.log(requestUrl);
fetch(requestUrl).then(function (response) {
if (response.status === 200) {
console.log(response.status);
response.json().then(async function (data) {
AmazonResolver.create(data);
});
} else {
try {
changeStatusToNotVerified(userId);
console.log(response.status);
response.json();
console.log("err will not add amazon verification object");
} catch (err) {
console.log(err);
}
}
});
}
async function changeStatusToVerified(userId) {
try {
await purchaseFromAppObjectModel.findOneAndUpdate(
{
UserData: { $elemMatch: { userId: userId } },
},
{ $set: { status: "verified" } }
);
} catch (err) {
console.log(err);
}
}
I want to write down my question as a minimal one but i want you to see my functions.
// you can use sort aggregate function to sort users in desc order and update the last element first
async function changeStatusToVerified(userId) {
try {
await purchaseFromAppObjectModel.findOneAndUpdate(
{
UserData: { $elemMatch: { userId: userId } },
},
{ $set: { status: "verified" } },
{ sort: { userId: -1 }, upsert: true, returnNewDocument: true }
);
} catch (err) {
console.log(err);
}
}
OR
async function changeStatusToVerified(userId) {
try {
await purchaseFromAppObjectModel.findOneAndUpdate(
{
UserData: { $elemMatch: { userId: userId } },
},
{ $set: { status: "verified" } },
{ sort: { userId: -1 } }
);
} catch (err) {
console.log(err);
}
}
if any one passes by here later on , this worked for me :
.findOneAndUpdate(
{
UserData: { $elemMatch: { userId: userId } },
},
{ $set: { status: "verified" }, limit: 1 }
)
.sort({ $natural: -1 });

Sequelize MySQL update value copy from other table

I'm trying to make a controller that will do something like this:
UPDATE bankapplication_accounts
SET last_successful_logged = last_present_logged
WHERE id = 1
My controller in sequelize looks like this:
exports.updateLastLoggedDate = (req, res) => {
User.findOne({
where: {
id: req.params.userId,
},
}).then(user => {
if (user) {
User.update(
{
last_successfull_logged: user.last_present_logged,
},
{ where: { id: req.params.userId } },
).then(() => {
res.status(200).send('logout correct');
});
}
});
};
Can this controller write better?
There are 2 ways
1:
exports.updateLastLoggedDate = (req, res) => {
User.findOne({
where: {
id: req.params.userId,
},
}).then((user) => {
if (user) {
user.update({
last_successfull_logged: user.last_present_logged,
}).then(() => {
res.status(200).send("logout correct");
});
}
});
};
2:
User.update(
{
last_successfull_logged: user.last_present_logged,
}, /* set attributes' value */
{
where: {
id: req.params.userId,
},
}, /* where criteria */
).then(() => {
res.status(200).send("logout correct");
});

mongodb/mongoose findOneandUpdate how to get index and delete object

So I am having event object, which have comments, and comments have likes array.
What I currently can do is to add like to comments array of event object.
My schema looks similar to this:
creator: {
type: Schema.Types.ObjectId,
ref: 'User'
},
comments: [
{
user: {
type: Schema.Types.ObjectId,
ref: 'User'
},
text: {
type: String,
required: true
},
likes: [
{
user: {
type: Schema.Types.ObjectId,
ref: 'User'
}
}
]
}
]
}
And my current add like to comments function looks like this:
commentLike: async (req, res) => {
console.log('working', req.params.id, req.params.idas, req.params.commentID);
Events.findOneAndUpdate(
{ _id: req.params.idas, comments: { $elemMatch: { _id: req.params.commentID } } },
{ $push: { 'comments.$.likes': { user: req.params.id } } },
(result) => {
res.json(result);
}
);
}
Params: idas- event._id, commentID: comment id, id: user._id
The problem is that i can add endless likes since, I have no logical operation to check if user already liked it, and im really strugling, in this findoneandupdate function to do that. But thats on problem, another thing what I want to do is unlike comment, and Im having atrouble at figuring it out, on how to get user index from likes array so i can slice that index out, currently my function is looking like this:
deleteLike: async (req, res) => {
console.log('working', req.params.id, req.params.idas, req.params.commentID);
Events.findOneAndUpdate(
{ _id: req.params.idas, comments: { $elemMatch: { _id: req.params.commentID } } },
{
$push: {
'comments.$.likes': {
$each: [],
$slice: 0 //there instead of 0 should be user index
}
}
},
(result) => {
res.json(result);
}
);
}
On this function im also using findoneandupdate function, which is probably not a good idea? Was trying to use findandremove, but it removes entire event object.
So i managed to to it, by using pull operator.
Working delete comment like fuction
deleteLike: async (req, res) => {
console.log('working', req.params.id, req.params.idas, req.params.commentID);
Events.findOneAndUpdate(
{ _id: req.params.idas, comments: { $elemMatch: { _id: req.params.commentID } } },
{
$pull: { 'comments.$.likes': { user: req.params.id } }
},
(result) => {
res.json(result);
}
);
}
};

Categories

Resources