# How DBX Implements MongoDB Document CRUD Operations with Pagination

> Learn how DBX implements MongoDB CRUD with pagination. It uses shell-style commands, server-side skip/limit, and client-side row caps for efficient data handling.

- Repository: [skyler/dbx](https://github.com/t8y2/dbx)
- Tags: how-to-guide
- Published: 2026-07-04

---

**DBX implements MongoDB document CRUD operations with pagination by parsing shell-style text commands into structured bridge requests that leverage server-side `skip` and `limit` parameters, then normalizing driver results into a uniform tabular format with client-side row caps.**

The open-source **t8y2/dbx** repository provides a shell-style interface for MongoDB that handles complex document operations through a centralized execution pipeline. Understanding how DBX implements MongoDB document CRUD operations with pagination reveals a sophisticated architecture that balances user-friendly syntax with efficient data retrieval and safety controls.

## Parsing Shell-Style Commands into Structured Requests

### The Command Parser Architecture

At the entry point in [`packages/node-core/src/database.ts`](https://github.com/t8y2/dbx/blob/main/packages/node-core/src/database.ts), DBX parses textual MongoDB commands using specialized `parseMongo*` helpers. The **`parseMongoFindCommand`** function (lines 36-66) extracts the collection name, filter objects, projection, sort order, and pagination parameters from strings like `db.projects.find({}).skip(20).limit(10)`.

For write operations, **`parseMongoWriteCommand`** (lines 130-150) creates strongly-typed command objects with a `kind` property identifying the operation as `"insert"`, `"update"`, or `"delete"`. Similarly, **`parseMongoCountDocumentsCommand`** handles count queries by preparing a simplified find operation with `limit` set to 1.

## Executing CRUD Operations Through the Desktop Bridge

### Read Operations with Server-Side Pagination

Once parsed, read commands flow through **`mongoFindDocuments`** (lines 33-44), which constructs a JSON payload for the DBX desktop bridge. The bridge executes the native MongoDB driver call at the endpoint `/data/mongo/find-documents`, respecting the `skip` and `limit` values extracted during parsing. This ensures pagination happens server-side before data crosses the process boundary.

### Write and Aggregation Operations

For document modifications, **`executeMongoWrite`** (lines 66-90) dispatches to `/data/mongo/insert-documents` or update/delete endpoints. The bridge distinguishes between `updateOne` and `updateMany` using the `many` flag from the parsed command.

Aggregation pipelines use **`mongoAggregateDocuments`**, which forwards the pipeline stages to the bridge. After the bridge response, DBX applies result slicing for aggregations that lack explicit limit stages, ensuring consistent pagination behavior.

## Result Normalization and Pagination Enforcement

### Converting Documents to Tabular Results

MongoDB's JSON documents transform into a uniform **`QueryResult`** structure via **`mongoDocumentsToQueryResult`** (lines 150-167). This helper builds the column list dynamically from all returned document keys and normalizes nested values into a flat row format suitable for tabular display.

### Client-Side Row Limits

The central **`executeQuery`** routine (lines 770-840) enforces pagination through **`resolveMaxRows`** (lines 24-26), which caps results to a default of **100 rows** or the caller-specified `maxRows` value. While `find` operations leverage the bridge's server-side `limit`, aggregation results receive client-side slicing after the bridge response to ensure the cap is respected.

## Safety Controls for Dangerous Operations

DBX implements security gates via **`evaluateMongoWriteSafety`** and **`evaluateMongoAggregateSafety`** (lines 80-84). These functions block dangerous aggregation stages like `$out` and `$merge` unless the environment variable **`DBX_MCP_ALLOW_DANGEROUS_SQL`** is set to `1`. This prevents accidental data destruction or unintended collection creation during CRUD operations.

## Practical Code Examples

### Paginated Find Queries

```typescript
import { executeQuery } from "dbx/packages/node-core/src/database.js";

const config = { /* Mongo connection config */ };
const sql = 'db.projects.find({ "status": "open" }).sort({ "createdAt": -1 }).skip(20).limit(10)';

const result = await executeQuery(config, sql);
// result.columns: ["_id", "status", "createdAt", ...]
// result.rows: Array of up to 10 documents (skipping first 20)

```

### Counting Documents

```typescript
const countSql = 'db.projects.countDocuments({ "status": "open" })';
const countResult = await executeQuery(config, countSql);
// countResult.columns: ["count"]
// countResult.rows: [{ count: 123 }]

```

### Inserting and Updating Documents

```typescript
// Insert a single document
const insertSql = 'db.projects.insertOne({ "name": "Demo", "active": true })';
await executeQuery(config, insertSql);
// Returns row_count: 1

// Update multiple documents
const updateSql = 'db.projects.updateMany({ "active": false }, { $set: { "active": true } })';
const updateResult = await executeQuery(config, updateSql);
// Returns row_count: number of documents updated

```

### Aggregation with Row Limits

```typescript
const aggSql = 'db.sales.aggregate([ { $match: { "year": 2025 } }, { $group: { _id: "$region", total: { $sum: "$amount" } } } ])';
const aggResult = await executeQuery(config, aggSql);
// Returns up to 100 rows by default; override via QueryOptions.maxRows

```

## Summary

- **DBX parses shell-style commands** using `parseMongoFindCommand` and `parseMongoWriteCommand` to extract CRUD parameters and pagination directives from textual input.
- **Server-side pagination** occurs via the desktop bridge at `/data/mongo/find-documents`, which passes `skip` and `limit` directly to the MongoDB driver before returning data.
- **Result normalization** happens through `mongoDocumentsToQueryResult`, converting JSON documents into a standardized tabular format with columns and rows.
- **Safety enforcement** blocks dangerous operations like `$out` and `$merge` unless `DBX_MCP_ALLOW_DANGEROUS_SQL` is enabled.
- **Row limits** default to 100 via `resolveMaxRows`, with client-side enforcement ensuring predictable memory usage across all query types.

## Frequently Asked Questions

### How does DBX handle pagination for large MongoDB result sets?

DBX implements a two-layer pagination strategy. First, the parser extracts `skip` and `limit` values from shell-style commands and passes them to the desktop bridge, which applies server-side limits via the native MongoDB driver. Second, the `executeQuery` function enforces a client-side maximum row count through `resolveMaxRows`, ensuring that even aggregations without explicit limits return predictable result sizes.

### What is the maximum number of rows DBX returns by default?

By default, DBX caps all query results at **100 rows** through the `resolveMaxRows` utility in [`packages/node-core/src/database.ts`](https://github.com/t8y2/dbx/blob/main/packages/node-core/src/database.ts). Developers can override this default by specifying a custom `maxRows` value in the `QueryOptions` parameter when calling `executeQuery`.

### How does DBX protect against dangerous MongoDB operations?

DBX evaluates write and aggregate commands using `evaluateMongoWriteSafety` and `evaluateMongoAggregateSafety`. These functions automatically block destructive pipeline stages such as `$out` and `$merge` unless the environment variable `DBX_MCP_ALLOW_DANGEROUS_SQL` is explicitly set to `1`, preventing accidental data loss or schema changes.

### Can DBX execute raw MongoDB driver commands?

No, DBX does not expose raw driver access. Instead, it provides a shell-style abstraction layer where all commands are parsed, validated, and routed through the `executeQuery` pipeline. This ensures that every operation—including CRUD and pagination—passes through safety checks and result normalization before reaching the MongoDB instance.