Node.js API: Add CRUD Operations With Pagination, Filtering, Grouping, and Sorting Capabilities.

Add CRUD and Aggregation operations including Pagination, Sorting, Filtering and Partial Text Search to your Node.js REST API.

In my previous Node.js tutorial, I outlined the steps required to build a Node.js Authentication API with Email Verification, Image Upload and Password Reset Using JWT, Passport.js, and Sendgrid.

This tutorial will be a continuation of that tutorial, CRUD operations will be added for an ‘Event’ resource, users’ will have the ability to create, read, update and delete events.

The API will include:

Pagination: users can dictate how many results they want (limit) and can also page through the result by passing the ‘page’ number in the URL query parameters. Filtering: users can also specify an event date to filter by Partial Text Search: users can search by event name, regex is utilized to perform a search against the name column in the database. Grouping: by default, all events are grouped by date, users can set this to false Sorting: results can be sorted in ascending order(asc), which is the default or in descending order (desc)

Mongoose Aggregate constructor is used along with mongoose-aggregate-paginate-v2, a cursor based custom pagination library for Mongoose to add these capabilities.

What are aggregations?

Aggregation operations process data records and return computed results. Aggregation operations group values from multiple documents together and can perform a variety of operations on the grouped data to return a single result. MongoDB provides three ways to perform aggregation: the aggregation pipeline, the map-reduce function, and single-purpose aggregation methods.

Functionalities

view all events (limit result, page through result, define sort order, specify date, search by name) create events update event delete event

Full Demo

Requirements

Authentication API — you can follow this tutorial to create your own or feel free to pull from the GitHub repo master branch to follow along.

*Remember to create you .env file and run npm install .

Links

Step 1: Install Dependencies

The following packages will be used:

mongoose-aggregate-paginate-v2 , a cursor-based custom pagination library for Mongoose.

, a cursor-based custom pagination library for Mongoose. moment,

$ npm install mongoose-aggregate-paginate-v2 moment --save

Step 2: Model

In the models folder, create the file event.js

The Event model schema includes various fields including userId which references a user in the database ‘users’ table and has the type Schema.Types.ObjectId.

.....

userId: {

type: mongoose.Schema.Types.ObjectId,

required: true,

ref: 'User'

},

models/event.js

Step 3: Controller

In the controllers folder, create the file event.js .

event.js The event controller includes the following functions. index

retrieves all the events in the database, grouped by date. Checks the request query parameters for the following (page, limit, sort_order, group, q and date). If the page or limit parameters are not present, the default values are used - page: 1 and limit: 5.

Pagination

let page = parseInt(req.query.page) || 1;

let limit = parseInt(req.query.limit) || 5;

Filtering and Partial Text Search (Stage 1)

In the first stage of the aggregation, the $match pipeline filters the events by the name field, this will be used for searching for events. $regex is used with the 'i' flag for a case-insensitive partial text search.



if (req.query.q) match.name = { $regex: req.query.q, $options: 'i'}; ----- In order to filter by date, we use the moment package to calculate the date for the next day and use the comparison operators to query date greater than or equal to the specified date and less than the next day. if (req.query.date) {

let d = moment(req.query.date);

let next_day = moment(d).add(1, 'days'); // add 1 day



match.start_date = {$gte: new Date(d), $lt: new Date(next_day)};

}

Grouping (Group By) (Stage 2)

$group object is created, In the second stage of the aggregation, the $group pipeline groups the events by the start_date field. In order to achieve this, aobject is created 1) The _id of the group is set to the field we want to GROUP BY, in this case, the start_date field, the $dateToString operator is used to convert the start date object to a string with the specified format. data of the group uses $push operator to specify the fields required, in this case 2) Theof the group usesoperator to specify the fields required, in this case $$ROOT system variable is used to select all fields. $group: {

_id: {$dateToString: {format: "%Y-%m-%d", date: "$start_date"}},

data: {$push: "$$ROOT"}

} ----- All results are grouped by default but users can set the group request query parameter to 0 or false. The parameter value is checked, if the group parameter is not present or set to 1 or true, the results are grouped by default.

Sorting (Stage 3)