DEV Community

loading...
Cover image for Complete REST API with diskdb, Node, and Express in 5 minutes

Complete REST API with diskdb, Node, and Express in 5 minutes

lennythedev profile image Lenmor Ld ・Updated on ・5 min read

Following from Part 1 and Part 2, we had a working server but the changes are lost when server is restarted 😠. That sucked, so now time to database the, err ... data! πŸ’ΎπŸ™‚πŸ₯«
(πŸ₯« <- this is supposed to be a database)

NoSql databases

Compared to SQL databases with tables and rows, NoSql has collections and documents:

database > collections > documents
Enter fullscreen mode Exit fullscreen mode

For example:

(database) data_db > 
  (collection) movies: [{}, {}, {}] > 
    (document) movie: { "id": "tt0110357", "name": "The Lion King", "genre": "animation"},
Enter fullscreen mode Exit fullscreen mode

And did I mention no tables ?
no_sql_joke

For details on the whole SQL vs NoSql, check out this article:

What is diskdb ?

Diskdb allows you to use a file-based database with a mongodb-like API. Think SQLite for mongo. But why?

  • Quick, simple, and fast - no more installation or config files; perfect for whipping a prototype server with some persistence
  • db is stored along with your code, in regular JSON file, so easy to maintain without extra tooling
  • No sign-up needed - No more signing up and getting tons of emails

why not?

  • Very simple with limited API functionality
  • Really not for Production

For the record, I loved mLab since it was easy, fast and free up to 500MB. But it was recently acquired by MongoDB and replaced with Atlas. I'll make a separate article for a cloud-based DB with Atlas as well.

Headstart

We'll use the base server files from the previous lesson here:
Quick REST API with Node + Express

Let's get started!

1. Create database file

Create /data/movies.json.
Data will be our database and movies will be our collection.

...
data/
    /movies.json
server.js
...
Enter fullscreen mode Exit fullscreen mode

Init movies.json with an empty array

[]
Enter fullscreen mode Exit fullscreen mode

2. Exclude data files from Nodemon

If you are using nodemon, you wouldn't want the server to restart for every change in the database files, i.e. an infinitely restarting server 😡

Add nodemonConfig to package.json, with a command to ignore /data.

"scripts": {...},
"nodemonConfig": { "ignore": [ "data/*" ] },
...
Enter fullscreen mode Exit fullscreen mode

3. Install diskdb

$ npm install diskdb
Enter fullscreen mode Exit fullscreen mode

4. Import and connect to db

The syntax is:
db.connect('/path/to/db-folder', ['collection-name']);

// server.js
...
// diskdb connection
const db = require('diskdb');
db.connect('./data', ['movies']);
Enter fullscreen mode Exit fullscreen mode

This effectively creates a connection to the 'data' db, and 'movies' collection.

4. Add a movie to test out connection

// server.js
...
// add first movie
if (!db.movies.find().length) {
   const movie = { id: "tt0110357", name: "The Lion King", genre: "animation" };
   db.movies.save(movie);
}
console.log(db.movies.find());
Enter fullscreen mode Exit fullscreen mode

Nice and simple!
db.[collection].save(object) to add a document
db.[collection].find() to get all current docs

We're only adding this movie if the db is initially empty,
or else we'll end up with lots of Lion Kings with different _ids 😨
🦁🦁🦁🦁🦁🦁🦁

This should give you something like this

Successfully connected to : ./data
[ { id: 'tt0110357',
    name: 'The Lion King',
    genre: 'animation',
    _id: 'fed8db042fac4892bb96fd72ad13290e' } ]
Enter fullscreen mode Exit fullscreen mode

Notice that it added a _id to our item, used as a global id like in mongodb.

5. CRUD to REST to DB

Now that you've seen Create and Read all, here's the complete roundup of the db operations in diskdb syntax for each CRUD - REST route handler.

For details on the REST - HTTP table and route handlers, check out prev post .

Also note that collection here is movies for our example.

CRUD Operation REST operation Diskdb Operation
Create POST /items db.[collection].save(object)
Read One GET /items/:id db.[collection].find(query)
Read All GET /items db.[collection].find()
Update PUT /items/:id db.[collection].update(query, data, options)
Delete DELETE /items/:id db.[collection].remove(query, multi)

6. Changing to diskdb operations

Using the table, we could now replace all of our memory-based operations with the db equivalent.

i. Create βž•

server.post("/items", (req, res) => {
   const item = req.body;
   console.log('Adding new item: ', item);
   // add new item to db
   db.movies.save(item);
   // return updated list
   res.json(db.movies.find());
});
Enter fullscreen mode Exit fullscreen mode

ii. Read one πŸ•΅οΈ

server.get("/items/:id", (req, res) => {
   const itemId = req.params.id;
   const items = db.movies.find({ id: itemId });
   if (items.length) {
      res.json(items);
   } else {
      res.json({ message: `item ${itemId} doesn't exist` })
   }
});
Enter fullscreen mode Exit fullscreen mode

iii. Read all πŸ•΅οΈ

server.get("/items", (req, res) => {
   res.json(db.movies.find());
});
Enter fullscreen mode Exit fullscreen mode

iv. Update ✏️

server.put("/items/:id", (req, res) => {
   const itemId = req.params.id;
   const item = req.body;
   console.log("Editing item: ", itemId, " to be ", item);

   db.movies.update({ id: itemId }, item);

   res.json(db.movies.find());
});
Enter fullscreen mode Exit fullscreen mode

v. Delete ❌

server.delete("/items/:id", (req, res) => {
   const itemId = req.params.id;
   console.log("Delete item with id: ", itemId);

   db.movies.remove({ id: itemId });

   res.json(db.movies.find());
});

Enter fullscreen mode Exit fullscreen mode

Test it out

Add a new one.

$ curl -X POST -H "Content-Type: application/json" --data '{"id": "tt0109830", "name": "Forrest Gump", "genre": "drama"}' http://localhost:4000/items
Enter fullscreen mode Exit fullscreen mode

Fetch all.
From browser: http://localhost:4000/items

Fetch one.
From browser: http://localhost:4000/items/tt0110357

Update it.
Maybe you think Forrest Gump is an action movie, because of all the war sequences and all the running. πŸ”«πŸŽ–οΈπŸƒβ€β™‚οΈ

$ curl -X PUT -H "Content-Type: application/json" --data '{"genre": "action"}' http://localhost:4000/items/tt0109830

...{"id":"tt0109830","name":"Forrest Gump","genre":"action"}...
Enter fullscreen mode Exit fullscreen mode

Delete it.

curl -X DELETE http://localhost:4000/items/tt0468569
Enter fullscreen mode Exit fullscreen mode

Some cleanup 🧹

Db is working! Now we can remove the unneeded static data file: data.js.
Don't forget to remove the line from server.js that imports it

let data = require('./data');

Here's the complete Code

Quick db with Node + Express + diskdb

hackerman

"Okay, that was nice. But what can I do with this? "

βœ… Serving HTML files
βœ… REST API
βœ… Database persistence

Now, this is an actual server for a small project. Add more routes, save some data in the db through API requests. And when you want to reset the db, just reset movies.json to [].

Next up:

(In progress): Using a Cloud DB with Node and Express

This article is part of a Node+Express series I'm working on.

For the meantime, if you can't get enough of Node+Express πŸ€“,
checkout my Node workshop (Gihub repo and slides):

GitHub logo lenmorld / node_workshop

Build a server and API for your next web application, using Node, Express and MongoDB

Node workshop

Create a server + REST API for your next web application!

In this workshop, we’ll discuss concepts and put them to practice with activities, all about web servers The code and concepts here would be a great foundation for your next web project Topics include, but not limited to:

  • Using Node and Express to build a web server and REST API
  • Understanding routing, request and response
  • Implementing CRUD with HTTP methods
  • Building a server-rendered website using templates
  • Connecting to a Cloud NoSQL database: MongoDB Atlas DB
  • User authentication with sessions, cookies and tokens
  • Using external APIs, such as Github Jobs, Giphy, Spotify

Previous Events

Material

Preview slides: Google Drive document

Material: Notion link

Code

to follow workshop:

$ git checkout dev
$ node server.js

to dev latest

$ git checkout master
$
…



Here we discussed:

  • Using Node and Express
  • Routing, request and response
  • Building a REST API
  • Server-rendered templates
  • Connecting to a NoSQL (mongo) database
  • Using external APIs, such as Spotify
  • and much more!

Happy server-ing! πŸ€“

Now, if I could find a better emoji for a database than πŸ₯«

Discussion (6)

pic
Editor guide
Collapse
sebring profile image
J. G. Sebring

Thanks, this was very handy as a dev db for demos or when backend are slacking, hehe.

I use this and added collection as a parameter.

server.get('/:collection/:id', (req, res) => {
  const collection = req.params.collection
  const id = req.params.id
  const item = db[collection].find({id})
  // validate
  res.json(item)
}
Collapse
mfazz profile image
Matt

Awesome articles, this was fantastic in helping me setup and get an understanding of API with Express and nodejs.

Can't wait for the 'Using a Cloud DB with Node and Express' part to come out!

Collapse
manlystump profile image
ManlyStump

Really enjoying these straight-to-the-point tuts. Just wanted to mention your "Test it out" section has the "Fetch one" and "Fetch all" URL's the wrong way around!

Collapse
lennythedev profile image
Lenmor Ld Author

Thanks for the catch.πŸ‘ I updated that part.

I'm gonna get to the next article of this series soon. I really appreciate the support πŸ˜€

Collapse
jmskippy profile image
jmskippy

Thanks...You made it really simple :-)

Collapse
lennythedev profile image