
Soft Delete đ – Node.js, MongoDB
In this article, we will teach you, how you can implement soft delete in your Node.js app with MongoDB as database.
We also created a tutorial on how to do soft delete in Laravel, check our tutorial here.
Soft delete đ is useful when you do not want to actually delete the record from database, but mark the data as deleted.
You might have seen “This message has been deleted” on WhatsApp đŦ when you delete a message. That was soft delete. Because if you actually delete the message from database, then you would have no reference if there was a message at that time.
It is also helpful in cases where you want to allow the user to delete some data, but wants the administrator đ¨đģâđŧ to see the data. So when user deletes the data, it will not actually delete the data from database. It will simply hide it from user, but administrator can still see it. Only administrator can actually delete the data.
We will use “users” as entity for the sake of this tutorial.
In this article, you will learn:
- Insert users in MongoDB
- Fetch non-trashed users
- Soft delete a user
- Fetch trashed users
- Restore a user
- Permanently delete a user
1. Insert users in MongoDB â
Following API will insert a new document in MongoDB “users” collection using Node.js:
// API to insert data
app.post("/insert", async function (request, result) {
// Get input fields
const name = request.fields.name || "";
// Insert data in database
await db.collection("users")
.insertOne({
name: name,
deletedAt: null // This will save the time when user was deleted
});
// Return response to the client
result.json({
status: "success",
message: "User has been inserted."
});
});
It will get user name from client app and insert a new document in “users” collection. Note that it creates another field “deletedAt” and set it’s value to null. Having NULL value means that the user is not deleted.
2. Fetch non-trashed users
Then we are going to fetch all the users that are not deleted.
// API to fetch non-trashed users
app.post("/fetch", async function (request, result) {
const users = await db.collection("users")
.find({
deletedAt: null
}).toArray();
result.json({
status: "success",
message: "Users has been fetched.",
users: users
});
});
Here we are using filter to fetch all the records where deletedAt
field is null.
3. Soft delete a user âĄ
Now we will create an API that will soft delete a user.
// API to move the user to trash can
app.post("/delete", async function (request, result) {
// Get user ID
const _id = request.fields._id || "";
// Don't delete the document,
// just update the deletedAt field
await db.collection("users")
.updateOne({
_id: ObjectId.createFromHexString(_id)
}, {
$set: {
deletedAt: new Date()
}
});
result.json({
status: "success",
message: "User has been moved to trash can."
});
});
Here, we are first getting the user ID from client app. Then we are setting the deletedAt
field to the current date.
If you run the /fetch
API again, you will not see that user’s data in the response. Even though the record exists in the database, it will not be returned.
4. Fetch trashed users
Now that we have trashed the user, we need to find a way to see all those trashed users. So we will create an API that will return all the users that has been soft-deleted.
// API to see all trashed users
app.post("/trashed", async function (request, result) {
const users = await db.collection("users")
.find({
deletedAt: {
$ne: null
}
}).toArray();
result.json({
status: "success",
message: "Trashed users has been fetched.",
users: users
});
});
At this point, you can give administrator 2 options, either:
- Restore the user
- Delete the user permanently
5. Restore a user âŠī¸
Restoring the user will simply set the deletedAt
field of user back to null
, like it was when user was created.
// API to restore a user
app.post("/restore", async function (request, result) {
const _id = request.fields._id || "";
await db.collection("users")
.updateOne({
_id: ObjectId.createFromHexString(_id)
}, {
$set: {
deletedAt: null
}
});
result.json({
status: "success",
message: "User has been restored."
});
});
This will also receive a user ID that needs to be restored. If you call the /fetch
API again, you will see that user in the response.
6. Permanently delete a user đ
Permanently deleting a user will actually deletes the user from database. There will no way to restore it once done (unless you have a backup đ of your database).
// API to actually delete the user from database
app.post("/delete-permanently", async function (request, result) {
const _id = request.fields._id || "";
await db.collection("users")
.deleteOne({
$and: [{
_id: ObjectId.createFromHexString(_id)
}, {
deletedAt: {
$ne: null
}
}]
});
result.json({
status: "success",
message: "User has been permanently deleted."
});
});
Usually, this access is given to super admin only.
Bonus âī¸
One more thing you can do, is if you have saved the user ID in other collections as well, then you can save the data in the dependent collections before removing them.
For example, if you have an “orders” collection, where you are saving user’s orders in the following format:
{
"_id": ObjectId("1234567890"),
"userId": ObjectId("0987654321")
}
If you permanently delete the user, then this order’s data will be lost as well. So best practice is to:
- Fetch the user.
- Put in orders collection.
- Delete the user.
Following is the code for that:
const user = await db.collection("users")
.findOne({
_id: ObjectId.createFromHexString(_id)
});
if (user == null) {
result.json({
status: "error",
message: "User not found."
});
return;
}
await db.collection("orders")
.updateMany({
userId: user._id
}, {
$set: {
user: {
_id: user._id,
name: user.name
}
}
});
Now, when you delete the user, your “orders” collection will save the user data for historical use.
{
"_id": ObjectId("1234567890"),
"userId": ObjectId("0987654321"),
"user": {
"_id": ObjectId("0987654321"),
"name": "Adnan"
}
}
Conclusion đ
So that’s it. That’s how you can create a soft delete feature in your Node.js application with MongoDB as backend. It is very helpful in almost every project and I would recommend everyone must apply it. Whenever user delete something, soft delete it so if user done that by mistake, he will be able to recover it.