NodeJS, ExpressJS, Redis, MongoDB - series #03
Tags: node, express, mongodb, database
Published: 2021-02-04 02:08:22


## Intro
These two code snippets have the identical behavior.
What does the code do?

See if it's intuitive enough to understand it just be reading it.
Read the "Notes" section below for the full explanation.

Snippet a.
```js
app.post(apiEnum.api_findgroup_artistyearsformed, async (req, res) => {
  res.json(
    await mgArr_redis(dbEnum.nlpdb, collEnum.songsColl, "artistyearsformed"
      { $match: { formed: { $exists: true } } },
      { $group: { _id: "$formed", count: { $sum: 1 } } },
      { $project: { _id: 0, formed: "$_id", count: 1 } },
      sort({ count: -1, hw: 1 }),
    ));
});

```

Snippet b.
```js
app.post(apiEnum.api_findgroup_artistyearsformed, async (req, res) => {
  res.json(
    await mgArr_redis(dbEnum.nlpdb, collEnum.songsColl, "artistyearsformed",
      matchExists("formed"),
      groupCount("formed"),
      renameGroupKey("formed"),
      sortDescSecondaryAsc("count", "formed"),
    ));
});
```


## Notes
* Code snippet A is the raw MongoDB database query syntax
* Code snippet B is simply a wrapper func around each stage of the query pipeline.

* The DB call returns this datashape. It gives a list of the count of bands formed in each year:
```js
/*
  { count: 13, formed: '2001' },
  { count: 10, formed: '2000' },
  { count: 14, formed: '1999' },
  { count: 4, formed: '1998' },
*/
```


* The mongoDB query is wrapped in a Node.js ExpressJS route.
Thus this query will return the data to those who are authorized to access the route:
```js
app.post(apiEnum.api_findgroup_artistyearsformed, async (req, res) =>
```

* As an aside, only registered domains can successful access this route, by way of this configuration (but we'll talk more about secure routes later):
```js
app.use(cors({ credentials: true, origin }));
```


* This resultset is very stable data, so it is a candidate for caching. I use a variant of mgArr, called mgArr_redis, which takes a third param as the cache key (in this case, "artistyearsformed") which uniquely identifies the resultset. The expiry time is configurable, and defaults to two hours. It takes a big load off your DB:
```js
await mgArr_redis(dbEnum.nlpdb, collEnum.songsColl, "artistyearsformed",
```

* The MongoDB collection holding these musician/artist documents has a field named "formed" which holds the 4 digit year.

* The matchExists("formed") is used to filter out artists who don't report their year formed

* As you can see, doing a "group" (aka "group by") in mongo is easy as cake.

* Notice the "Snippet b." is cleaner and more semantically rich in conveying what it does. You read it like the building blocks (stages) of a database query. The raw or wrapper syntaxes are interchangeable when using the "mgArr" utility func.

* Doing secondary (or third or any number) sorts are a cinch in MongoDB.



## What's Next?

* Today we covered,
** Routes with ExpressJS
** Securing your ExpressJS route
** Caching with Redis
** Grouping data in MongoDB

* If you have an questions, let me know

* As the series goes on, we'll go deeper, solving some amazing real world problems in style. :)