Safe MongoDB list queries from the query string you already use

Build safe MongoDB query objects from API query params. Allow-lists for search, filters, and sorts; predictable pagination; one function between HTTP and the driver.

6+

Query concerns in one API

1

Public entrypoint

0

Framework lock-in

One place for list semantics

Handlers often reimplement parsing, caps, and allow-lists. Centralise that logic once and keep routes thin: validate input, call buildMongoQuery, pass the result to your data layer.

Without a Shared Layer

  • Different allow-lists per route
  • Pagination edge cases handled inconsistently
  • Harder to review or test query behaviour

With mongo-query-tools

  • Configure allowed fields and defaults once
  • Same skip, limit, and sort rules for every list endpoint
  • Try payloads in the playground, then ship

What you configure

Each option maps cleanly to documented query parameters or internal API contracts.

  • Search

    Case-insensitive substring match across fields you allow, combined as a safe logical OR.

  • Filtering

    Only keys in your allow-list become Mongo predicates. Unknown keys are ignored.

  • Sorting

    Parse sort strings into Mongo sort objects, constrained by allowed field names.

  • Pagination

    Consistent page, limit, skip, and hard caps so list APIs behave the same everywhere.

  • Conditional filters

    Merge tenancy or feature-flag rules alongside static defaults in one place.

  • TypeScript

    Typed configuration and results for handlers, services, and tests.

Works With

  • Express
  • Next.js Route Handlers
  • Fastify
  • Plain Node.js

Anywhere you can read a shallow query object—no ORM required.

Install from npm

No code generation: pass the same shape your adapter already gives you from req.query or equivalent.

npm install mongo-query-tools

Usage sketch

TypeScript example

typescript
import { buildMongoQuery } from "mongo-query-tools";

const query = {
  page: "1",
  limit: "20",
  search: "john",
  sort: "-createdAt",
  status: "active",
};

const opts = buildMongoQuery(query, {
  searchableFields: ["name", "email"],
  allowedFilters: ["status", "role"],
  allowedSorts: ["createdAt", "name"],
  defaultFilters: { isDeleted: false },
  defaultSort: "-createdAt",
  maxLimit: 100,
});

db.collection("users")
  .find(opts.filter)
  .sort(opts.sort)
  .skip(opts.skip)
  .limit(opts.limit);

Get started in three steps

1

Define the surface

List searchable fields, allowed filters and sorts, defaults, and max page size next to your route or schema.

2

Call the builder

Forward the raw query record into buildMongoQuery and pass filter, sort, skip, and limit to MongoDB.

3

Verify in the playground

Paste JSON from logs or tests, compare output with production config before you merge.

Ready to standardise list endpoints?

Read the API reference or try the live playground backed by the published package.