Rango speaks the MongoDB PHP API but stores everything in PostgreSQL. Understanding the mapping helps you reason about performance, write SQL against the same tables, and know what to expect from each operation.
Rango translates MongoDB concepts into native PostgreSQL structures:
| MongoDB concept | PostgreSQL structure |
|---|---|
| Database | Schema |
| Collection | Table with _id and data columns |
| Document | Row, stored as JSONB in data |
| Index | B-tree index on a JSONB expression |
| Query operators | JSONB operators and conditions |
Every collection is a table with two columns: a TEXT _id primary key and a JSONB data column holding the full document. The _id is also kept inside the document so reads return it like any other field.
You never run migrations by hand. The first write to a collection creates the schema and table if they do not exist:
CREATE SCHEMA IF NOT EXISTS "app";
CREATE TABLE IF NOT EXISTS "app"."users" (_id TEXT PRIMARY KEY, data JSONB NOT NULL);Selecting a database or collection never touches PostgreSQL. The structure is created on demand the first time you insert or update.
When you insert a document without an _id, Rango generates a random 24-character hex string and uses it as the primary key. Provide your own _id whenever you need a stable, meaningful key.
Query operators compile to PostgreSQL JSONB conditions, dot-notation paths become -> and ->> accessors, update operators become jsonb_set-style expressions, and aggregation pipelines become nested SELECT statements. Because the result is ordinary SQL against ordinary tables, you can inspect, back up, and query the data with any PostgreSQL tool.
Rango covers the most common MongoDB use cases, but it does not reimplement the entire MongoDB feature set. The following features are currently out of scope:
$near and $geoWithin2dsphere), text, sparse, and TTL indexes are not, and the matching IndexInfo checks always report falseUpserts also need _id to be present in the filter, because Rango builds the primary key of the inserted document from it. An upsert without _id in the filter raises an exception.
This list reflects the current state of Rango. Features may be added over time, so check the changelog and the aggregation and indexes pages for what is available in your version.