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

Building Node and Express Stuff in 5 minutes (4 Part Series)

1) Your first Web Server with Node and Express in 5 minutes 2) REST API with Node and Express in 5 minutes 3) Complete REST API with diskdb, Node, and Express in 5 minutes 4) 🌱 Complete REST API with MongoDB Atlas cloud, Node, and Express in 10 minutes

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

For example:

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

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
...

Init movies.json with an empty array

[]

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/*" ] },
...

3. Install diskdb

$ npm install diskdb

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']);

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());

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' } ]

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());
});

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` })
   }
});

iii. Read all πŸ•΅οΈ

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

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());
});

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());
});

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

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"}...

Delete it.

curl -X DELETE http://localhost:4000/items/tt0468569

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 an API for your next web application, using Node, Express and MongoDB

Node workshop

to follow workshop:

$ git checkout dev
$ node server.js

to dev latest

$ git checkout master
$ npm start

Create a .env file on root

NODE_ENV=development
PORT=4000
MONGO_DB_CONNECTION_STRING=YOUR_CONNECTION_STRING_HERE
# API keys go here



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 πŸ₯«

Building Node and Express Stuff in 5 minutes (4 Part Series)

1) Your first Web Server with Node and Express in 5 minutes 2) REST API with Node and Express in 5 minutes 3) Complete REST API with diskdb, Node, and Express in 5 minutes 4) 🌱 Complete REST API with MongoDB Atlas cloud, Node, and Express in 10 minutes

Posted on by:

lennythedev profile

Lenmor Ld

@lennythedev

webdev @ Autodesk | Someone used to call me "Learn more", and I'm spending forever to live up to it. You'll find me dabbling in random stuff πŸ‘¨β€πŸ’» or missing a wide open shot in πŸ€

Discussion

markdown guide
 

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)
}
 

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!

 

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 πŸ˜€

 

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!