DEV Community

Cover image for MongoDB without Mongoose
Kamal Hossain
Kamal Hossain

Posted on

MongoDB without Mongoose

Lets suppose you just want to store a bunch of email addresses as your subscribers in your MongoDB database. Nothing else.

There is no need to implement an entire driver to handle this. Yes, of course, drivers provide many advantages to make our lives easy. But to keep things simple and lightweight we can use only MongoDB for CRUD operation without a mongoose.

What about validation? Don't worry, packages like sanitize-html can be used in MongoDB to validate data before storing to a database.

Get the Source code if you don't want to follow along.

Let's get started.


Create a nodejs Server

Run the followings in your terminal:

mkdir mongodb-without-mongoose && cd mongodb-without-mongoose
Enter fullscreen mode Exit fullscreen mode

These will create a folder called mongodb-without-mongoose and navigate to the folder.

npm init -y && npm install express mongodb --save
Enter fullscreen mode Exit fullscreen mode

To initialize package.json file in our source folder to install dependencies, we run the first part of the command. And the second part is for installing the express.js and MongoDB as our dependencies.

Now let's create an app.js file in your project folder. And fill the file with the followings to create a simple server:

const express = require('express')
const mongodb = require('mongodb')

const app = express()
let db

const PORT = 5000

app.get('/testRoute', (req, res) => res.end('Hello from Server!'))

app.listen(PORT, () => {
  console.log(`Node.js App running on port ${PORT}...`)
})
Enter fullscreen mode Exit fullscreen mode

To start the server run:

node app.js
Enter fullscreen mode Exit fullscreen mode

Here we have just created a simple server at port 5000. On localhost:5000/testRoute it will send the response, Hello from Server!.


Connect to mongodb from server

In this example, we are going to connect the local MongoDB of windows. We are not going to any cloud services of MongoDB. So let's add some lines in our app.js to establish the connection.

// ...
const app = express()
let db

let connectionString = `mongodb://localhost:27017/crud`
Enter fullscreen mode Exit fullscreen mode

This is the default connection string of windows to connect to the local database. Now let us connect to MongoDB by using this string.

// ...
const app = express()
let db

let connectionString = `mongodb://localhost:27017/crud`

mongodb.connect(
  connectionString,
  { useNewUrlParser: true, useUnifiedTopology: true },
  function (err, client) {
    db = client.db()
    app.listen(5000)
  }
)
Enter fullscreen mode Exit fullscreen mode

Here above the MongoDB.connect() taking the connection string as the first argument, after that a second argument is an object for not getting the deprecation warnings from MongoDB.
And finally, the last argument is the callback function which can be used after MongoDB.connect() function trying to connect to MongoDB.

In our case, we are storing the database in a variable for further use and also started the app for listening in port 5000.

Now that we have our database connected, let's create some endpoints to make the app useful.

// ...

mongodb.connect(
  connectionString,
  { useNewUrlParser: true, useUnifiedTopology: true },
  function (err, client) {
    db = client.db()
    app.listen(5000)
  }
)

app.post('/create-data', function (req, res) {
  // Sending request to create a data
  db.collection('data').insertOne({ text: req.body.text }, function (
    err,
    info
  ) {
    res.json(info.ops[0])
  })
})
Enter fullscreen mode Exit fullscreen mode

Here we have set up a post request to our app to /create-data. Here we are using the db.collection() to specify the collection name in the crud database that we have connected already.

In this method, we are chaining the insertOne() to create a document in the collection. We are passing two arguments in this function.

The first one is the text property with the string from the req.body object. And the second one is the callback function to do some stuff when the insetOne() method tries to insert the document to the collection.

In our callback function, we have two arguments, err and info. We are going to retrieve our collection of documents from info.ops[0] and then simply send back the response to the requested user.

Let's try a post request on localhost:5000/create-data with the following json data from postman.

{
  "text": "Kamal Hossain"
}
Enter fullscreen mode Exit fullscreen mode

What have got?

Well, I have got a 500 Internal Server Error with a bunch of HTML values in response. So let's check the console where is server is running.

TypeError: Cannot read property 'text' of undefined

I have got some lines in our console and the first line is telling this above. So why this is happening?

Well, we have sent JSON data to our nodejs app, where the server was created with the help of express.js. So by default, it can't read any JSON Object from incoming requests. So we have to add a line for that.

// ...

mongodb.connect(
  connectionString,
  { useNewUrlParser: true, useUnifiedTopology: true },
  function (err, client) {
    db = client.db()
    app.listen(5000)
  }
)

app.use(express.json())
Enter fullscreen mode Exit fullscreen mode

This will take care of the current problem. Let's save & restart our server. Then send the request again.

{
  "text": "Kamal Hossain",
  "_id": "5f5c27353c14cc09309d4440"
}
Enter fullscreen mode Exit fullscreen mode

This is the response I have got from our server. Which was sent from the insertOne() methods callback function. The _id is the unique id to identify our this particular document across the database.

Now that we have created our first document lets create a route to get all the documents from our collection via get request.

// ...

app.post('/create-data', function (req, res) {
  // Sending request to create a data
  db.collection('data').insertOne({ text: req.body.text }, function (
    err,
    info
  ) {
    res.json(info.ops[0])
  })
})

app.get('/', function (req, res) {
  // getting all the data
  db.collection('data')
    .find()
    .toArray(function (err, items) {
      res.send(items)
    })
})
Enter fullscreen mode Exit fullscreen mode

Here we are setting the route as / which will be the root route of any domain. In our case the localhost:5000. Here we are using the find() method to get all the documents from the collection. Lastly, we are chaining the toArray() method to put all the documents in an array, and in the callback of toArray() we are sending the response back.

Lets do a get request in postman to localhost:5000/

[
    {
        "_id": "5f5c27353c14cc09309d4440",
        "text": "Kamal Hossain"
    }
]
Enter fullscreen mode Exit fullscreen mode

Now let's add two more routes in our app to update and delete a document.

// ...

app.get('/', function (req, res) {
  // getting all the data
  db.collection('data')
    .find()
    .toArray(function (err, items) {
      res.send(items)
    })
})

app.put('/update-data', function (req, res) {
  // updating a data by it's ID and new value
  db.collection('data').findOneAndUpdate(
    { _id: new mongodb.ObjectId(req.body.id) },
    { $set: { text: req.body.text } },
    function () {
      res.send('Success updated!')
    }
  )
})
Enter fullscreen mode Exit fullscreen mode

In our /update-data route are are mainly updating a document by findOneAndUpdate(). In this method we are passing the object Id that needs to be updated, then we are passing the updated text. And lastly, we are just sending the success response.

Let's now delete a document.

// ...

app.put('/update-data', function (req, res) {
  // updating a data by it's ID and new value
  db.collection('data').findOneAndUpdate(
    { _id: new mongodb.ObjectId(req.body.id) },
    { $set: { text: req.body.text } },
    function () {
      res.send('Success updated!')
    }
  )
})

app.delete('/delete-data', function (req, res) {
  // deleting a data by it's ID
  db.collection('data').deleteOne(
    { _id: new mongodb.ObjectId(req.body.id) },
    function () {
      res.send('Successfully deleted!')
    }
  )
})
Enter fullscreen mode Exit fullscreen mode

In our delete-data route we are using delete() method to delete the document from collection. And lastly sending a response to the client in the callback function.


Originally published at https://kamalhossain.me/blog/mongodb-without-mongoose

Discussion (3)

Collapse
abhinavpanse profile image
abhinavpanse

How can we make Schemas in plain mongodb without using mongoose.???

Collapse
longwater1234 profile image
Davis Tibbz

Actually it is possible! MongoDB has introduced this since v3.6. Schema Validation. And its actually more powerful in the fact that it is Database Level Strict and not just Application level (like mongoose). See developer.mongodb.com/article/mong...

Collapse
kamalhossain profile image
Kamal Hossain Author

Actually we can't. For that we must need to use mongoose.