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)