Chris Collins

Tools · infra

MongoDB playground

A mongosh-like console on a MongoDB that runs in your browser — with sample data, an aggregation pipeline builder that previews every stage, explain plans drawn as a tree (COLLSCAN vs IXSCAN), schema inference and $jsonSchema validators, a reference with runnable examples — and a real-server mode that speaks MongoDB's wire protocol through the gitwebsite app.

Added

Works with

How to use it

Type mongosh commands — db.restaurants.find({ cuisine: "Thai" }), db.orders.aggregate([…]), db.c.createIndex({ a: 1 }) — and see replies as mongosh prints them. Two backends sit behind the console:

  • Playground (the default) — a MongoDB 7.0 emulation in this page. It answers the same database commands a server does (find, getMore, aggregate, insert, update, delete, findAndModify, createIndexes, explain, collMod…) with the same replies and error codes. Query, update and aggregation operators are evaluated by mingo; collections, indexes, unique keys, TTL, validation, cursors and the query planner are this page’s. Sample data… loads restaurants (240), a shop (400 orders, 60 customers, 20 products) or IoT readings (576 hourly readings from 8 sensors, with an alarm spike and gaps). Tick Keep data in this browser to keep the playground between visits.

  • Real server — your own MongoDB, reached through the gitwebsite app’s TCP relay. The page speaks MongoDB’s wire protocol itself: BSON, OP_MSG, the hello handshake and SCRAM-SHA-256 / SCRAM-SHA-1 authentication.

How to use it

Console. Enter runs a statement; when a bracket is still open, Enter starts a new line (Shift+Enter always does). ↑ ↓ walk the history, Tab completes collection names after db., methods after db.coll. and operator names after $, and the line below the prompt shows the syntax of the method you are typing. show dbs, show collections, use <db>, it (the next 20 documents of a cursor), help and cls work as in mongosh. Values: ObjectId("…"), ISODate("…"), new Date(), NumberLong("…"), NumberDecimal("…"), UUID("…"), /regex/i; variables with const x = …. This shell parses the JavaScript subset mongosh users type — it does not run JavaScript, so functions (forEach(d ⇒ …)) are not supported. Show wire messages lists each OP_MSG sent to a real server with its size.

Pipeline. Build an aggregation one stage at a time: pick the operator, write its body, and each stage shows what comes out of it — the count and the first ten documents — as you type (on a real server, when you press Preview). Stages can be switched off, moved and removed; $out and $merge are not previewed. Run in console, Explain and Copy as shell take the whole pipeline. The example pipelines load their dataset first.

Explain. Write a find() (or aggregate(), count(), distinct()) and see the plan the server chose drawn as a tree — data flows upwards from the scan — with what each stage examined, cards for documents returned, keys and documents examined, and warnings: a collection scan, a blocking in-memory SORT, many keys or documents examined for few results, or a covered query. Below, the collection’s indexes, an index suggested by the ESR rule (Equality fields, then the Sort, then Ranges) with a button to create it and explain again, and hint() buttons to compare indexes. explain() in the console prints a one-line summary with a link to the drawing. Full screen shows the console or the plan alone.

Schema. Samples a collection with $sample and lists every field path: its BSON types (a bar per type), how often it is present, examples and ranges — what your documents really look like. Generate from the sample writes a $jsonSchema from it (types, and required for fields present in every document); Check the sample lists the sampled documents that would fail it, with MongoDB-style reasons; Apply (collMod) sets it as the collection’s validator with the level and action you choose.

Docs. Query, projection and update operators, aggregation stages, expressions and accumulators, shell methods and index types — each with its syntax, a summary, a link to the MongoDB manual and an example. Try it runs the example in a fresh playground with its sample data; Run in console loads that data into the current playground database and runs it there.

History. Kept per connection, only in this browser. Search it, run a command again, put it back in the console, export or import it as JSON, or clear it. Lines with passwords (createUser, auth, changeUserPassword, pwd:) are never saved.

Connecting to a real MongoDB

Browsers cannot open TCP connections, so the page reaches your server through the gitwebsite app’s companion (or gw serve) running on your computer. Choose Real server, type the server’s host:port, a username, password and auth database if it needs them, and Connect. The app asks you to approve the page the first time, and to allow a new server on its TCP allow-list (add 127.0.0.1:27017 ahead of time on its Companion page, or with gw companion tcp add).

  • Authentication: auto asks the server which SCRAM mechanisms the user has (saslSupportedMechs) and uses SCRAM-SHA-256 when it can. The server’s signature is checked, so a server that does not know the password cannot pretend to. TLS is not supported (the relay carries plain TCP): for a remote or TLS-only server, connect through an SSH tunnel to a local port.

  • On a real server, commands that drop or delete everything ask first: dropDatabase, drop, dropIndexes, renameCollection, deleteMany({}), updateMany({}, …), pipelines with $out or $merge, collMod, user and role changes, shutdown, killOp, replica-set and sharding commands, setParameter, fsync.

  • Passwords stay in memory unless you tick Remember (then they are kept in this browser’s storage, readable by anyone using it). They never go into links or history.

Limits

  • The playground stores numbers as JavaScript numbers: NumberLong, NumberInt and NumberDecimal become doubles there (a real server keeps them, and the console prints Long('…') and Decimal128('…')). Not in the playground: $text and text indexes, geospatial queries and 2dsphere indexes, $where and JavaScript, collations, time-series collections, transactions and sessions, change streams, users and roles, replication and sharding. Natural order is insertion order.

  • The planner is a simulation, not mongod’s: it builds index bounds, walks the index key by key the way mongod’s index scan does (seeks included), and picks the candidate that examines the least, where mongod races the candidates for a few steps. On the sample datasets its plans, keys examined and documents examined match MongoDB 7.0’s for the queries tested (single, compound, multikey and partial indexes, $in, prefix and unanchored regexes, $ne, sorts, covered queries, limits and skips); $or, index intersection and the plan cache are not simulated. Timings are the browser’s.

  • Index and storage sizes in stats() are estimates. The TTL monitor sweeps every 60 seconds, as on a server.

  • The shell is a subset of mongosh: no functions or loops, no rs./sh. helpers (use db.adminCommand), no load(). bulkWrite sends one command per operation.

  • Real server: no TLS, no compression, no Kerberos/LDAP/X.509 authentication; a cursor’s further batches come with it. The wire client is tested against MongoDB 7.0.

How it is tested

The BSON encoder and decoder pass the BSON corpus files of every type in the MongoDB specifications repository (718 valid cases including Decimal128, 255 decode and parse errors). SCRAM is checked against the RFC 5802 and RFC 7677 examples and MongoDB’s own SCRAM-SHA-1 vector, OP_MSG framing byte by byte. Every example in the reference runs on a throwaway MongoDB 7.0 and in the playground through the same shell, and the replies must be identical (125 of 125, field order included); the planner’s plans, keys examined and documents examined are compared with mongod’s for 24 queries on the restaurants data.

Linking to an example

Links can be written by hand. Add the tab after #: console, pipeline, explain, schema, docs or history. A link never connects to a server and never carries a password.

Parameter Meaning Example

example

Load a scenario below (sample data included) and run it

example=index-esr

ds

Load a sample dataset into the playground: restaurants, shop or iot

ds=shop

cmd

A console command: run in the playground, or filled in (not run) for a real server. Several lines are allowed (%0A between them)

cmd=db.orders.countDocuments()

db

The database to use

db=shop

doc

Open a reference entry (group:name)

doc=stage:$lookup

q

A search in the Docs tab

q=array

conn

playground or server

conn=server

target

The server’s host:port (with conn=server)

target=127.0.0.1:27017

Presets for example=:

example= Shows

first-query

Counts, a filtered and sorted find with a projection, distinct values (open)

index-esr

Documents examined before and after a compound index in Equality–Sort–Range order, and the plan drawn (open)

revenue

Revenue by country and month: $match, $group with $dateToString, $sort — a preview after each stage (open)

lookup

Orders joined to customers and products with $lookup and $unwind (open)

iot-hourly

Six-hour buckets of a sensor’s readings with $dateTrunc, averages, maxima and alarm counts (open)

schema

The orders' inferred schema, ready to become a validator (open)

validation

A $jsonSchema validator rejecting a bad document, with errInfo (open)

counters

Upserts: a page-view counter with $setOnInsert and a sequence with findOneAndUpdate (open)

arrays

Array updates: $push with $each/$sort/$slice, and arrayFilters (open)

More: ?ds=restaurants&cmd=…explain(…) explains a query on the restaurants; ?doc=update:$push#docs opens one reference entry.

Runs entirely in your browser — network requests go only to the services named on this page.