Originally posted on cri.dev
monk's github repo description says it all
The wise MongoDB API
A tiny layer that provides simple yet substantial usability improvements for MongoDB usage within Node.JS.
I love the super simple api
const db = require('monk')('localhost/db') const users = db.get('users')
Use it in production 💯
Below you can see a real-world snippet of the db connection for pomodoro.cc (source code here).
The file lib/db.js
const monk = require('monk') const logger = require('pino')() logger.info('process.env.NODE_ENV', process.env.NODE_ENV) logger.info('MONGO_URL set?', !!process.env.MONGO_URL) module.exports = monk(process.env.MONGO_URL)
Nothing more, nothing less.
You could use it then to create your models and repositories around it:
For example lib/models/users.js
:
const db = require('../db') const users = db.get('users') users.createIndex({ _id: 1 }) users.createIndex({ createdAt: 1 }) module.exports = users
use cases
stream a collection
In pomodoro.cc I use this feature to stream documents from the users collection, to update a users twitter avatar.
Here you can find the full code snippet:
await users.find({ twitterAvatarNotFound: { $exists: false }, $or: [{ twitterAvatarUpdatedAt: { $lt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 7) } }, { twitterAvatarUpdatedAt: { $exists: false } }] }) .each(async (user, { pause, resume }) => { // ... process user twitter avatar }) .catch(err => console.error(err))
Aggregations
Again, as a real-world production use-case, I take pomodoro.cc's daily analytics aggregation for Pro users.
In this example I want to showcase how a daily aggregate of documents can be done with MongoDB, monk and Node.js.
About aggregations from the official docs:
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.
An example from pomodoro.cc source code
return pomodoros.aggregate( [ { $match: { userId: monk.id(userId) } }, { $project: { doc: '$$ROOT', year: { $substr: [`$${field}`, 0, 4] }, month: { $substr: [`$${field}`, 5, 2] }, day: { $substr: [`$${field}`, 8, 2] } } }, { $group: { _id: { year: '$year', month: '$month', day: '$day' }, docs: { $push: '$doc' } } }, { $project: { _id: 0, day: { $concat: ['$_id.year', '-', '$_id.month', '-', '$_id.day'] }, docs: '$docs' } }, { $sort: { day: -1 } } ] )
Here I aggregated documents of a collection by date, matched by a single userId.
upsertion - update or insert
what an upsert operation is in a few words:
Insert a New Document if No Match Exists
from the official docs you can see that
Optional. If set to true, creates a new document when no document matches the query criteria. The default value is false, which does not insert a new document when no match is found.
It as simple as providing the upsert: true
option to the update
function:
const result = await books.update( { item: "ZZZ135" }, // Query parameter { // Replacement document item: "ZZZ135", stock: 5, tags: [ "database" ] }, { upsert: true } // Options )
The result will look something like this:
{ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : ObjectId("5da78973835b2f1c75347a83") }
this gives us more information on what the update operation actually did.
Top comments (0)