Easy Guide to Use findOneAndUpdate in MongoDB Using Nodejs

A MongoDB database has multiple collections. These collections can store millions of documents(data in MongoDB is called a document). MongoDB has various methods to fetch the documents from a collection such as find(), findOne(), findOneAndUpdate(), etc.

We already have covered the find() and findOne() methods, in this tutorial we will provide a comprehensive guide to using the method findOneAndUpdate() of MongoDB in Nodejs.

findOneAndUpdate() method in MongoDB

findOneAndUpdate() method is used to select matching documents on the basis of some given condition and update the very first document accordingly.

This method required two arguments, the first is the filter to find the documents and the second is the update to update the very first document.

Syntax:

db.collection.findOneAndUpdate(filter, update)

It return the updated document if the optional argument returnNewDocument is set to true or the returnDocument is set to after.

How to Use findOneAndUpdate in MongoDB in Nodejs Application?

This guide assumes you already have MongoDB installed on your machine. If not, click here to see the steps to install MongoDB on Windows.

Let us assume we are running a drone-selling platform where users can sell their drones. We will allow them to edit their listings or even delete them.

Since it is a basic application, we will not focus on the authorization of the listings. Our project will also not have any styling, sorry 😊.

Follow the steps below to learn how.

  • Create a Nodejs application by navigating into the desired location. Open the terminal and pass this command:
npm init -y
  • Create the entry point file:
touch index.js
  • Install all the required packages:
npm i mongoose express method-override ejs

We will also install method-override API by Express to be able to use PUT or DELETE requests.

  • Now, open your code editor and use all the installed packages with the help of the require method:
const express = require('express');
const app = express();
const path = require('path');
const methodOverride = require('method-override');
const mongoose = require('mongoose');
const { urlencoded } = require('express');

We must also use the path module to help us manage the file paths. This will also help us run our Nodejs project from any directory.

  • Create a port where the app must listen:
app.listen(3000, () => {
    console.log('Connected to PORT 3000...');
})
  • Let us now add some of these lines of code below. We will be setting up a MongoDB local database server connection using mongoose. Then, we set up the EJS view engine and assigned a folder to store our views.

We also have to set up the method override middleware in our application.

mongoose.connect('mongodb://localhost:27017/droneStore', { useNewUrlParser: true, useUnifiedTopology: true })
    .then(() => {
        console.log(`CONNECTED TO MONGO!`);
    })
    .catch((err) => {
        console.log(`OH NO! MONGO CONNECTION ERROR!`);
        console.log(err);
    })

app.set('views', path.join(__dirname, '/views'))
app.set('view engine', 'ejs')

app.use(express.urlencoded({ extended: true }))
app.use(methodOverride('_method'))
  • Now, let us create our schema and model for the drones. Create a models folder in your project directory and inside it, create product.js. Here’s where our schema will reside and from where we will export our model:
const mongoose = require('mongoose');
const productSchema = new mongoose.Schema({
    name: {
        type: String,
        required: true
    },
    price: {
        type: Number,
        required: true,
        min: 0
    },
    utility: {
        type: [String],
        enum: ['Monitoring or Inspection', 'Security', 'Delivery', 'Photography', 'Recreation']
    },
    weight: {
        type: String,
        lowercase: true
    },
    onSale: {
        type: Boolean,
        default: false
    }
})
const Drone = mongoose.model('Drone', productSchema);
module.exports = Drone;
  • You will now have to import the exported model in index.js:
const Drone = require('./models/product.js')
  • I have already created some documents in my database before I proceed to use findOneAndUpdate in MongoDB. Now, I will create a basic GET route to the Edit page for the drone listing:
app.get('/drones/:id/edit', async (req, res) => {
    const { id } = req.params;
    const foundDrone = await Drone.findById(id);
    res.render('drones/edit.ejs', { foundDrone, utilities })
})

We can simply hit this route on our browser to visit the page.

  • To be able to edit the “utility” feature of a drone in the next step, I will create an array before the edit GET route consisting of the options. I will then iterate over this array in my view to be able to change the utility option:
const utilities = ['Monitoring or Inspection', 'Security', 'Delivery', 'Photography', 'Recreation'];
  • I will create a views folder in my project directory and create an edit.ejs file in it. This is the HTML markup it will consist of:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Edit Drone</title>
</head>

<body>
    <h1> Edit <%= foundDrone.name %> Drone</h1>
    <form action="/drones/<%= foundDrone.id %>?_method=PUT" method="POST">

        <label for="name">Add a Drone Name</label>
        <input type="text" name="name" id="name" value="<%= foundDrone.name %>">
        <hr>

        <label for="price">Add a Price</label>
        <input type="number" name="price" id="price" value="<%= foundDrone.price %>">
        <hr>

        <label for="utility">Add Utilities</label>
        <select name="utility" id="utility">
            <% for (let utility of utilities){ %>
                <option value="<%= utility %>" <%=foundDrone.utility==utility ? 'selected' : '' %>>
                    <%= utility %>
                </option>
                <% } %>
        </select>
        <hr>

        <label for="weight">Add a Weight in Grams or Kg</label>
        <input type="text" name="weight" id="weight" value="<%= foundDrone.weight %>"
            placeholder="'grams' or 'kilograms' in lowercase">
        <hr>

        <button type="submit">EDIT DRONE</button>

    </form>
</body>
</html>

Notice we have used the method override API to convert a POST request to PUT in Express. An HTML form only allows us to use two types of requests: GET or POST.

So, this is what our edit page looks like. You can simply copy and paste the ID of a document into the URL.

Use FindOneAndUpdate In MongoDB Edit Page
  • Let us finally create a PUT route to use the findOneAndUpdate method in the MongoDB database and update the values:
app.put('/drones/:id', async (req, res) => {
    const { id } = req.params;
    const updateDrone = await Drone.findOneAndUpdate(id, req.body, { runValidators: true });
    res.redirect(`/drones/${updateDrone.id}`)
})
  • Let us edit some values on the SV – LaserX AW205 Drone. Once the document is updated it will redirect us to the view page of the document with the changes made.

Output:

Use FindOneAndUpdate In MongoDB Result Page

Conclusion

The findOneAndUpdate() method is used in finding the document, it selects the very document to update it according to the argument passed. It selects the very first document for a given condition to update it. Hope this tutorial helps you to understand the findOneAndUpdate() method in MongoDB using Node.js.

Reference

https://www.mongodb.com/docs/manual/reference/method/db.collection.findOneAndUpdate/

Aneesha S
Aneesha S
Articles: 172