How to delete documents from two collections in mongodb - node.js

As of now I am able to delete the specific files from filestorage.files collection based on query but I am trying to delete the specific chunks from filesstorage.chunks collection based on files_id. Can someone please suggest me the good approach to achieve it.
Should I use aggregations ? or any looping mechanism ?
Please find the below details
filestorage.files collection:
[{
"_id": {
"$oid": "635a68aa0651c2d869fc3fd3"
},
"length": 878669,
"chunkSize": 261120,
"uploadDate": {
"$date": {
"$numberLong": "1666869418612"
}
},
"filename": "pexels-lucie-liz-3165335_2022-10-27T11-16-58.jpg",
"contentType": "image/jpeg",
"metadata": {
"originalname": "pexels-lucie-liz-3165335.jpg",
"parentFolder": {
"$oid": "636cd238692344da47f3e301"
},
"path": "files/Folder1/Folder3/pexels-lucie-liz-3165335_2022-10-27T11-16-58.jpg"
}
},
{
"_id": {
"$oid": "635a68aa0651c2d869fc3fd4"
},
"length": 878669,
"chunkSize": 261120,
"uploadDate": {
"$date": {
"$numberLong": "1666869418612"
}
},
"filename": "nature-3165335_2022-10-27T11-16-58.jpg",
"contentType": "image/jpeg",
"metadata": {
"originalname": "nature-3165335.jpg",
"parentFolder": {
"$oid": "636cd238692344da47f3e301"
},
"path": "files/Folder1/Folder3/nature-3165335_2022-10-27T11-16-58.jpg"
}
}]
filestorage.chunks collection :
[{
"_id": {
"$oid": "635a68aa0651c2d869fc3fe6"
},
"files_id": {
"$oid": "635a68aa0651c2d869fc3fd3"
},
"n": 0,
"data": {
"$binary": {
"base64" : "xyz"
"subType": "00"
}
}
},
{
"_id": {
"$oid": "635a68aa0651c2d869fc3fd5"
},
"files_id": {
"$oid": "635a68aa0651c2d869fc3fd3"
},
"n": 0,
"data": {
"$binary": {
"base64" : "abcd"
"subType": "00"
}
}
}]
Here is what I have tried :
delete_folder_files: async (ctx:any) => {
// here I am able to delete all the files but confused how to connect chunks schema and delete chunks // based on files_id.
await FileStorage.deleteMany({'metadata.parentFolder': ctx.params.id});
await FileChunk.deleteMany({files_id : ? })
ctx.status = HttpStatusCode.OK;
}

As I can see you are deleting the file ids . So after that you do not have any relation to delete the chunks in fileChunk collection .
Here is what I am thinking , First get all the file ids as an array and later you can delete the chunks with the folder_ids by querying them as array.
const file_ids = await FileStorage.find({'metadata.parentFolder': ctx.params.id },{_id:1}).distinct('_id');
await FileStorage.deleteMany({'metadata.parentFolder':ctx.params.id });
await FileChunk.deleteMany({files_id:{$in:file_ids}});
Note : Please check the performance of the query by uploading multiple files.

Related

Posting an aggregation as a new document/collection

In my client I have a form that is sent and stored in Mongo. Made an aggregation to get the name of the people that selected a same place, date and time. Now I would like to create a Mongo document containing all matches as collections so whenever there is a match in place, date and time of people you can get it in a collection. This is what I have so far:
router.get('/match', async (req, res) => {
const matchs = await Forms.aggregate([
{
$group: {
_id: { Date: "$date", Time: "$time", Place: "$place" },
Data: { $addToSet: {Name: "$firstName", Surname:"$surname"}},
count: { $sum: 1 }
}
},
{
$match: {
count: { $gte: 2}
}
},
]);
res.json(matchs)
});
This is the result that I would like to store in Mongo:
{
"_id": {
"Date": "2022-04-20",
"Time": "15:00",
"Place": "Mall"
},
"Data": [
{
"Name": "Carl",
"Surname": "Man"
},
{
"Name": "Christian",
"Surname": "Max"
}
],
"count": 2
}
{
"_id": {
"Date": "2022-04-20",
"Time": "13:00",
"Place": "Restaurant"
},
"Data": [
{
"Name": "Felix",
"Surname": "Sad"
},
{
"Name": "Liu",
"Surname": "Lam"
}
],
"count": 2
}
You can use $out as the last stage in your pipeline. In the following example, matching_collection will contain the result of your pipeline.
{ $out : "matching_collection" }
https://www.mongodb.com/docs/v4.2/reference/operator/aggregation/out/
You can also check $merge, it could be helpful as well.

fetch array based length - mongoose

I have visitors array. Based on length I want to fetch first 40(highest visted) videos. Is there any query in mongoose for this?
"videos": [],
"description": "Runs for indai",
"status": 1,
"_id": "5e68ee512d3fe53a4426fea5",
"likes": [],
"visited": [{
"_id": "5e690d28797f5b05e066104d",
"user": "::1"
},
{
"_id": "5e690d14797f5b05e066104c",
"user": "::1"
},
{
"_id": "5e690cf7797f5b05e066104b",
"user": "::1"
}],
"comments": [],
"embed": "https://wwdalkfa.com/idaa/46221",
"category": "Mathrubhumi",
"title": "Bdis idnc - Aria.",
"link": "https://www.mdaoa.com/video/46221/dafa",
"image": "https://www.mdaoa.com/media/videos/dstmb1/46221/1b.jpg",
"keywords": "adjal","DAfa",
"__v": 0
controller
exports.getTrendingVideos = async (req, res) => {
try {
const videos = await Video.find().limit(40);
res.send(videos);
} catch (error) {}
};
First, get the length of the array and then sort it, You can do it like this
const videos = await Video.aggregate([
{ $project: { visitedCount: { $size: '$visited' } } },
{ $sort: { $visitedCount: -1 } },
]).limit(40);

Find and remove by Id a subdocument in array with mongoose

I'm trying to delete a subdocuments in array with Mongoose.
My datas :
{
"_id": {
"$oid": "5d88dfe45feb4c06a5cfb762"
},
"spaces": [{
"_id": {
"$oid": "5d88dfe45feb4c06a5cfb76f"
},
"name": "Building 2",
"subSpace": [{
"_id": {
"$oid": "5d88dfe45feb4c06a5cfb771"
},
"name": "Basement"
}, {
"_id": {
"$oid": "5d88dfe45feb4c06a5cfb770"
},
"name": "Floors"
}]
}, {
"_id": {
"$oid": "5d88dfe45feb4c06a5cfb76c"
},
"name": "Building 4",
"subSpace": [{
"_id": {
"$oid": "5d88dfe45feb4c06a5cfb76e"
},
"name": "Basement"
}, {
"_id": {
"$oid": "5d88dfe45feb4c06a5cfb76d"
},
"name": "Floors"
}]
}]
}
For this example, we want to delete the subSpace Floors in Building 2 with this _id : 5d88dfe45feb4c06a5cfb771
My code (in the model) :
exports.removeSubSpaceById = (subSpaceId) => {
Residence.findOneAndUpdate( { "spaces.subSpace._id": '5d88dfe45feb4c06a5cfb771' },
{ $pull:
{ spaces:
{ subSpace:
{ _id: '5d88dfe45feb4c06a5cfb771' }}}}, function(err, result) {
console.log(result);
})
};
Output : console.log : my entire document
But the subSpace/Basement (5d88dfe45feb4c06a5cfb771) is still in my document.
Thanks for your help.
Use positional operator for nested array operations. MongoDb Docs
exports.removeSubSpaceById = (subSpaceId) => {
Residence.findOneAndUpdate({ "spaces._id": '5d88dfe45feb4c06a5cfb76f' },
{
$pull:
{
"spaces.$.subSpace": { _id: "5d88dfe45feb4c06a5cfb771" }
}
}, function (err, result) {
console.log(result);
})
}

how to find item in collection with $match

I have collection trusted contacts. I need to filter the document by the user. When I use method findOne I have a result, but when I use $match I got an empty array. I don't know why $match doesn't work for me.
Collection trusted contacts:
{
"_id": {
"$oid": "5d76008e4b98e63e58cb34cc"
},
"date": {
"$date": "2019-09-09T07:32:20.174Z"
},
"approvedTrustedContacts": [
{
"_id": {
"$oid": "5d764e411b7476462cf6b540"
},
"user": {
"$oid": "5c5ecaf6134fc342d4b1a9d5"
}
},
{
"_id": {
"$oid": "5d7750af52352918f802c474"
},
"user": {
"$oid": "5c64968cae53a8202c963223"
}
}
],
"pendingApprovalContacts": [],
"waitingForApprovalContacts": [],
"user": {
"$oid": "5d76008e4b98e63e58cb34cb"
}
},
{
"_id": {
"$oid": "5d7605f5e7179a084efa385b"
},
"date": {
"$date": "2019-09-09T07:32:20.174Z"
},
"approvedTrustedContacts": [
{
"_id": {
"$oid": "5d764e411b7476462cf6b541"
},
"user": {
"$oid": "5d76008e4b98e63e58cb34cb"
}
}
],
"pendingApprovalContacts": [],
"waitingForApprovalContacts": [],
"user": {
"$oid": "5c5ecaf6134fc342d4b1a9d5"
}
}
when I use method findOne
const user = await TrustedContacts.findOne({ user: "5d76008e4b98e63e58cb34cb" })
I have result
but when I use $match I got empty array
result1 = await TrustedContacts.aggregate([
{ $match: { user: "5d76008e4b98e63e58cb34cb" } },
]);
It Works,
const ObjectId = require('mongodb').ObjectId;
result1 = await TrustedContacts.aggregate([
{ $match: { user: ObjectId("5d76008e4b98e63e58cb34cb") } },
]);

Mongoose how to select certain object in embedded array

I had been searching around and still not able to find the correct answer.
Basically I have the below data model in mongodb
{
"_id": {
"$oid": "565db83bcd7bef020b1bdae8"
},
"userId": {
"$oid": "5653a3267827f178214918fc"
},
"targetUser": [
{
"userId": {
"$oid": "564663a5c0aefc151625b5e2"
},
"status": "Approved",
"_id": {
"$oid": "565db83bcd7bef020b1bdaea"
}
},
{
"userId": {
"$oid": "564548249bb75c600ff94cdd"
},
"status": "Sent",
"_id": {
"$oid": "565db884cd7bef020b1bdaed"
}
}
]
},
{
"_id": {
"$oid": "565db884cd7bef020b1bdaec"
},
"userId": {
"$oid": "564548249bb75c600ff94cdd"
},
"targetUser": [
{
"userId": {
"$oid": "5653a3267827f178214918fc"
},
"status": "Pending",
"_id": {
"$oid": "565db884cd7bef020b1bdaee"
}
}
]
}
How can I only return the follow data???
{
"userId": {
"$oid": "5653a3267827f178214918fc"
},
"targetUser": [
{
"userId": {
"$oid": "564663a5c0aefc151625b5e2"
},
"status": "Approved",
"_id": {
"$oid": "565db83bcd7bef020b1bdaea"
}
},
}
I had use the below code, but the result is return null
Connection.aggregate([
{$match:{userId:'5653a3267827f178214918fc'}},
{$unwind:'$targetUser'},
{$match:{'targetUser.status':'Approved'}},
{$group:{
_id:'$_id',
targetUser:{
$push:{
status:'$targetUser.status'
}
}
}}
],function(err,connections){
console.log(connections);
console.log(err);
})
Thank you so much for the help
From what I see, you don't need to aggregate, a simple find with a projection parameter will return what you need.
Connection.findOne({
userId: new ObjectId("5653a3267827f178214918fc")
}).select({
targetUser: {
$elemMatch: { status: "Approved" }
}
}).exec(callback);
But if you have more fields than userId and targetUser, you'll need to add them in the second parameter like this
Connection.findOne({
userId: new ObjectId("5653a3267827f178214918fc")
}).select({
targetUser: {
$elemMatch: { status: "Approved" }
},
oneMoreField: 1,
anotherField: 1
}).exec(callback);

Resources