MongoDB Query Runner for JSON

Paste a JSON array of documents and a MongoDB find filter — $gt, $in, $regex, $elemMatch, dotted paths and all — and see exactly which documents match. Add a projection, sort, skip and limit to reproduce a whole cursor chain, then export as JSON, NDJSON, CSV or a count. Runs entirely in your browser — no database, no upload, no sign-up.

Try:
Matching documents

About this tool

This is a MongoDB query runner for plain JSON. Paste a JSON array of documents, paste the same find filter you would hand to db.collection.find(...), and see exactly which documents come back — without a server, a connection string, or a scratch collection. It is built for testing a filter before it ships, explaining a query to a teammate, and slicing a JSON export down to the records you actually care about.

The query language is MongoDB's query-and-projection language. Supported operators:

MongoDB's matching rules are followed, not approximated: dotted paths such as team.name reach into sub-documents, a predicate on an array field matches when any element matches, and a missing field behaves the way the server behaves — {"age": null}, $ne, $nin and $not all match documents that do not have the field at all.

Worked example

Documents:

[
  {"name":"Ada","age":36,"team":{"name":"core"},"tags":["math","code"]},
  {"name":"Bo","age":24,"team":{"name":"infra"},"tags":["ops"]},
  {"name":"Cy","age":41,"team":{"name":"core"},"tags":["code","ops"]}
]

Query {"tags": {"$in": ["code"]}}, projection name, age, sort age:desc:

[
  {
    "name": "Cy",
    "age": 41
  },
  {
    "name": "Ada",
    "age": 36
  }
]

Both documents match because tags is an array and at least one element is "code". Switching the output format to Count only returns 2 instead.

Projection, sort, skip and limit

The four boxes below the filter reproduce a full cursor chain — find(query, projection).sort(...) .skip(...).limit(...):

Output is a JSON array (indented by default), NDJSON for piping line by line, CSV for a spreadsheet, or just the count.

Pasting a query straight from the shell or Compass

Shell-flavoured syntax is accepted, so a filter copied out of mongosh, Compass or an application log usually runs unmodified: unquoted keys ({ age: { $gt: 21 } }), single quotes, // and /* */ comments, trailing commas, /pattern/flags regex literals, and the ObjectId(), ISODate(), NumberLong(), NumberInt() and NumberDecimal() helpers. Strict JSON is a subset, so it works too. Because the input is JSON rather than BSON, ObjectId("…") and ISODate("…") compare as the string inside them, and the numeric helpers compare as plain numbers.

Limits and edge cases

FAQ

Does this connect to my MongoDB database?

No. It never opens a network connection. You paste the documents (a JSON array, a single object, or NDJSON) and the query, and everything is evaluated locally in your browser by a WebAssembly module. That is the point: you can test a filter against production-shaped sample documents without giving anything access to your cluster. To get sample documents out of a real deployment, run mongoexport --jsonArray or copy a result set out of Compass and paste it in.

Why does my query on an array field match more documents than I expected?

Because that is what MongoDB does. A predicate on an array field matches when any element satisfies it, so {"tags": "code"} matches {"tags": ["math", "code"]}, and {"scores": {"$gt": 90}} matches a document whose scores array holds a single value above 90 — even if other elements are far below it. When you need one element to satisfy every condition at once, use $elemMatch: {"items": {"$elemMatch": {"sku": "a", "qty": {"$gt": 5}}}} matches only documents where a single item is both SKU a and quantity greater than 5.

Why does `$ne` return documents that don't have the field at all?

Again, matching the server. In MongoDB a missing field is treated as null for query purposes, so {"age": {"$ne": 24}} matches documents with no age key, {"age": null} matches both an explicit null and a missing key, and {"age": {"$not": {"$gt": 30}}} matches documents that lack age too. If you want only documents that actually carry the field, add $exists: {"age": {"$exists": true, "$ne": 24}}.

Can I paste a query with unquoted keys, single quotes or `ObjectId()`?

Yes. The query box reads relaxed shell syntax, so { status: 'active', _id: ObjectId("64b8f0…") } parses as written, along with // and /* */ comments, trailing commas and /^ada/i regex literals. Because the documents are plain JSON rather than BSON, ObjectId("x") and ISODate("x") compare as the string x, and NumberLong(5) compares as the number 5 — which is normally what you want when the documents came out of mongoexport or an API response.

Why is `$where` rejected?

$where runs arbitrary JavaScript against each document, which needs a JavaScript interpreter this sandbox does not ship — and which MongoDB itself discourages for performance and security reasons. $expr and $jsonSchema are rejected for the same class of reason: they need the aggregation-expression evaluator and a JSON Schema validator. Rather than quietly ignoring them and returning the wrong documents, the tool fails with the operator name and the reason. Most $where filters can be rewritten with $and, $or, $regex and $mod.

How do I get a CSV of just a few fields?

Set the projection to the fields you want (short form is easiest: name, age, team.name) and switch the output format to CSV. The columns are the first-seen union of the returned documents' top-level keys, so every returned document contributes its keys in order, and a document missing a column gets an empty cell. Nested objects and arrays are written into the cell as compact JSON — flatten them with a dotted projection first if you want them in their own columns.

Developer & Automation Access

Run it from the terminal

Same engine as this page, headless — via the gizza CLI:

gizza tool mongo-query '[
  {"name":"Ada","age":36,"team":{"name":"core"},"tags":["math","code"]},
  {"name":"Bo","age":24,"team":{"name":"infra"},"tags":["ops"]},
  {"name":"Cy","age":41,"team":{"name":"core"},"tags":["code","ops"]}
]'

New to the CLI? Get gizza →

Open it by URL

Pre-fill and auto-run this tool with query parameters — the names match the API/CLI:

https://gizza.ai/tools/mongo-query/?data=%5B%0A%20%20%7B%22name%22%3A%22Ada%22%2C%22age%22%3A36%2C%22team%22%3A%7B%22name%22%3A%22core%22%7D%2C%22tags%22%3A%5B%22math%22%2C%22code%22%5D%7D%2C%0A%20%20%7B%22name%22%3A%22Bo%22%2C%22age%22%3A24%2C%22team%22%3A%7B%22name%22%3A%22infra%22%7D%2C%22tags%22%3A%5B%22ops%22%5D%7D%2C%0A%20%20%7B%22name%22%3A%22Cy%22%2C%22age%22%3A41%2C%22team%22%3A%7B%22name%22%3A%22core%22%7D%2C%22tags%22%3A%5B%22code%22%2C%22ops%22%5D%7D%0A%5D&query=%7B%22age%22%3A%20%7B%22%24gt%22%3A%2030%7D%2C%20%22tags%22%3A%20%7B%22%24in%22%3A%20%5B%22code%22%5D%7D%7D&projection=name%2C%20age&sort=age%3Adesc%2C%20name&skip=0&limit=0&format=json&pretty=true

Machine-readable descriptor: tool.json — title + parameters JSON Schema for agents.