Check out "Do you speak JavaScript?" - my latest video course on advanced JavaScript.
Language APIs, Popular Concepts, Design Patterns, Advanced Techniques In the Browser

q2m - a library for translating URL params to MongoDB query

q2m - a library for translating URL params to MongoDB query Photo by Robert Linder

I'm not open-sourcing very often anymore, but recently I finished developing a small tool called q2m that I believe is worth sharing. It's a library designed to convert URL parameters into MongoDB queries, which I needed for my latest project, a little SaaS called Lumina CMS.

Use case

The system I'm building is a headless CMS that needs to provide a flexible API for querying the data. Initially, I chose Firebase's Firestore as the database, but I found that it lacks query capabilities. As a result, I decided to switch to MongoDB.

The MongoDB query looks like this:

{
  "count": {
    "$gt": 20
  }
}

This query retrieves all records with a count greater than 20. There are various other query options that I decided to support. I considered two approaches for exposing this query language to API consumers:

  1. The simplest option is to accept the query directly as a payload.
  2. Alternatively, I could create a layer that acts as a transformer, accepting GET parameters and generating a MongoDB query.

I chose the second option because I believe accessing the content via GET directly is easier and provides a better developer experience. This is how q2m was born.

The library

The library is available as an npm module and can be installed using:

npm install q2m
# or
yarn install q2m

Using the library is straightforward. Here's an example:

const { parse } = require('q2m');

parse({ foo: 'bar' });
// { foo: { $eq: 'bar' }}

Initially, the parse function accepted an object, but I later decided to use the qs module and support a string as well. So the same example can also be written as:

parse('foo=bar');
// { foo: { $eq: 'bar' }}

The challenge was to support the main MongoDB query language syntax. I used TDD to ensure the library's functionality, as it involved many if-else statements.

Here's a slightly more complicated example:

parse('or[0][a]=>20&or[1][b]=$bar');
/*
{
  "$or": [
    {
      "a": {
        "$gt": 20
      }
    },
    {
      "b": {
        "$regex": "bar",
        "$options": "i"
      }
    }
  ]
}
*/

The library supports the following MongoDB operators: $eq, $ne, $exists, $exists, $gt, $gte, $lt, $lte, $in, $nin, $or, $and, $nor, and $regex.

If you enjoy this post, share it on Twitter, Facebook or LinkedIn.