Quickly build a blog api with QuickCrud.js

Quickly build a blog api with QuickCrud.js

An easy CRUD operation based on Factory pattern with Mongoose. There are four CRUD operations we can do:

·

5 min read

Mongoose is one of the best ORM so far for MongoDB. Their crud API is so good but we need to do a lot of repeated things over and over in order to do pagination, sorting and populating. For reducing the pain of your neck, here comes the magical tool QuickCrud.js

Let's quickly build a blog API with QuickCrud.js

Setup Express

Step 1

Install packages

npm init -y

yarn add express mongoose quick-crud

Step 2

Let's setup express server via index.js

const express = require('express')
const app = express()

// Body parser for accepting json from client
app.use(express.json())
app.use(express.urlencoded({ extended: true }))

app.get('/', (req, res) => {
    res.json({
        message: 'QuickCrud.js blog api'
    })
})

// Connect to db via mongoose
mongoose
    .connect(/*db_url*/)
    .then(() => {
        console.log('Database Connected.')
    })
    .catch((error) => {
        console.log('Database Connect Faield.')
    })

// Start server
app.listen(3000, () => {
    console.log('server running on http://localhost:3000')
})

Step 3

Then we will create a directory named models and write 2 model files here.

Post.js

const mongoose = require('mongoose')

const postSchema = new mongoose.Schema({
    title: String,
    body: String,
    categories: [
        // referencing the category model
        {
            type: mongoose.SchemaTypes.ObjectId,
            ref: 'Category'
        }
    ]
})

const Post = mongoose.model('Post', postSchema)
module.exports = Post

Category.js

const mongoose = require('mongoose')

const categorySchema = new mongoose.Schema({
    name: String
})

const Category = mongoose.model('Category', categorySchema)
module.exports = Category

Step 4

Create routes directory and put posts.js and categories.js on it. We will work with these two routes to illustrate QuickCrud.js

At first, let's create posts.js and categories.js base endpoints

// file: routes/posts.js
const Router = require('express').Router()

// Get post list
Router.get('/', (req, res) => {})

// Create a post
Router.post('/', (req, res) => {})

// Get a single post
Router.get('/:_id', (req, res) => {})

// Update a single post
Router.put('/:_id', (req, res) => {})

// Delete a post
Router.delete('/:_id', (req, res) => {})

module.exports = Router
// file: routes/categories.js

const Router = require('express').Router()

// Get category list
Router.get('/', (req, res) => {})

// Create a category
Router.post('/', (req, res) => {})

// Get a single category
Router.get('/:_id', (req, res) => {})

// Update a single category
Router.put('/:_id', (req, res) => {})

// Delete a category
Router.delete('/:_id', (req, res) => {})

module.exports = Router

And the update our index.js file to hook up these routes

const express = require('express')
const app = express()

// Body parser for accepting json from client
app.use(express.json())
app.use(express.urlencoded({ extended: true }))

// Routes
app.use('posts', require('./routes/posts'))
app.use('categories', require('./routes/categories'))

app.get('/', (req, res) => {
    res.json({
        message: 'QuickCrud.js blog api'
    })
})

app.listen(3000, () => {
    console.log('server running on http://localhost:3000')
})

Step 5

Now let's start doing magic with QuickCrud.js. As we are using this magical tool, we no longer need any controller file for routes. We have all sorts of crud functionality on QuickCrud.js out of the box which we have to do repeatedly on controllers.

In QuickCrud.js have 5 methods

  • index() - For fetching all resources with pagination and limiting
  • store() - Create a document
  • show() - Fetch a single resource with schema key
  • update() - Update an existing document
  • destroy() - Delete an existing document

Create category document

Route.post('/', async (req, res) => {
    const _doc = await qc.store(Category, req.body)
    res.json(_doc)
})

Response

{
    "_id": "xxx",
    "name": "cat 1",
    "__v": 0
}

Get All categories

For getting all categories, we have qc.index() method.

Route.get('/', async (req, res) => {
    const _docs = await qc.index(Category)
    res.json(_docs)
})

Response

Limiting and paginating with ?page and ?limit qc.index() method have 3 args: Model, Population, PagitionOption.

With PagitionOption of qc.index() we can do pagination and limiting resources list.

Route.get('/', async (req, res) => {
    const _docs = await qc.index(Category, {} , {
        page: +req.query.page,
        limit: +req.query.limit
    })
    res.json(_docs)
})

?limit=3&page=1

Page1

?limit=3&page=2 Page2

Update and Delete category

Updating and deleting is pretty straight forward with qc.destroy() and qc.update()

// Update a single category
Route.put('/:_id', async (req, res) => {
    let data = await qc.update(
        Category,
        {
            _id: req.params._id
        },
        req.body
    )

    res.json({
        message: 'Category updated',
        data
    })
})

// Delete a category
Route.delete('/:_id', (req, res) => {
    let data = await qc.destroy(Category, {
        _id: req.params._id
    })

    res.json({
        message: 'Category deleted',
        data
    })
})




Post endpoints

As like previous categories route, post's update and delete is dead simple and straight forward.

// Update a single post
Router.put('/:_id', (req, res) => {
    let data = await qc.update(
        Post,
        {
            _id: req.params._id
        },
        req.body
    )

    res.json({
        message: 'Post updated',
        data
    })
})

// Delete a post
Router.delete('/:_id', (req, res) => {
    let data = await qc.destroy(Post, {
        _id: req.params._id
    })

    res.json({
        message: 'Post deleted',
        data
    })
})

Lets create some posts with categories

create post

Now lets fetch all and single resource with categories population

// Get post list
Router.get('/', async (req, res) => {
    const _docs = await qc.index(Post, {} , {
        page: +req.query.page,
        limit: +req.query.limit
    } , 'categories')
    res.json(_docs)
})

// Get a single post
Router.get('/:_id', async (req, res) => {
    const _docs = await qc.show(Post, { _id: req.params._id }, 'categories')
    res.json(_docs)
})

Post list with categories population Post list with categories population

Single post with categories population Single post with categories population

Want to explore more? Checkout package documentation: npmjs.com/package/node-crud

Feel free to report any type of bug report or feature request. {% github kingRayhan/quick-crud %}

Source code