Query Syntax
monq’s simple query mode lets you filter and project in a single query string — no separator needed. Open it with /.
Search
Section titled “Search”A word with no field: searches every string field, and the results update as you type.
alice → "alice" in any string field (case-insensitive)alice berlin → both words, possibly in different fields"new york" → one phrasealice status:active → search AND status=activealice !berlin → "alice" somewhere, "berlin" nowhereEach term becomes a case-insensitive substring $regex over every string field and array of strings in the sampled schema, nested paths included (up to 40 fields), OR-ed together. Several terms AND together.
A term that parses as a value also matches fields of that type:
| Term | Also matches |
|---|---|
| 24 hex characters | objectid fields, including _id, by equality |
A number (42, -3.5) |
number fields by equality |
YYYY-MM-DD |
date fields within that UTC day |
| Detail | Behaviour |
|---|---|
| Live | Re-queries 300 ms after the terms change, once every term has 2+ characters. Enter still submits and records history |
| Special characters | A term containing :, <, >, = or ! must be quoted: "a:b". Regex characters are matched literally |
| Fields | Only fields the schema sample has seen. With none, the search matches nothing |
| Cost | Regex search can’t use an index; it scans the collection and times out after 10 s |
Excluding terms
Section titled “Excluding terms”Prefix a term with ! to hide documents that contain it: !stefan, !"new york". The term becomes { $nor: [ … ] } over the same fields a positive term searches, type-aware matches included, and ANDs with everything else. A document without any of those fields is kept. The prefix is ! rather than - because a bare -word excludes the field word from the projection.
Excluded terms aren’t highlighted, and the filter bar counts them: ⌕ regex · 12 fields · 1 excluded.
Matches are highlighted in the document list. The filter bar shows the engine and field count while a query searches, e.g. ⌕ regex · 12 fields. Switch to BSON mode (Tab) to see the generated $or.
Full-text search
Section titled “Full-text search”If the collection has a text index, press Ctrl+T in the query bar to switch search to $text. The terms become one $text: { $search: … }, with each term sent as a quoted phrase so that every term must match, just as in regex mode. $text uses the index, but it matches whole words (stemmed), not substrings, and skips the type-aware matching. Field tokens still combine with it:
alice status:active → { $text: { $search: "\"alice\"" }, status: "active" }Excluded terms become -"term" inside $search. $text needs at least one positive term, so a query with only excluded terms uses the regex $nor even when $text is on.
The choice is kept per tab. Without a text index, Ctrl+T shows a warning and search stays on regex.
Filters
Section titled “Filters”Equality
Section titled “Equality”Author:Peter → { "Author": "Peter" }Author:Peter State:Closed → { "Author": "Peter", "State": "Closed" }Comparisons
Section titled “Comparisons”age>25 → { "age": { "$gt": 25 } }age>=18 age<65 → { "age": { "$gte": 18, "$lt": 65 } }Ranges
Section titled “Ranges”Use field:lo..hi to express a range with a single token. Either bound can be omitted.
age:18..65 → { "age": { "$gte": 18, "$lte": 65 } }age:..65 → { "age": { "$lte": 65 } }age:18.. → { "age": { "$gte": 18 } }price:10.5..99.99 → { "price": { "$gte": 10.5, "$lte": 99.99 } }Date strings are automatically coerced to MongoDB ISODate values. YYYY-MM-DD is treated as start-of-day UTC.
createdAt:2025-01-15 → { "createdAt": ISODate("2025-01-15T00:00:00.000Z") }createdAt>2025-01-01 → { "createdAt": { "$gt": ISODate("2025-01-01T00:00:00.000Z") } }createdAt>=2025-01-01T12:00:00Z → { "createdAt": { "$gte": ISODate("2025-01-01T12:00:00.000Z") } }createdAt!=2025-06-15 → { "createdAt": { "$ne": ISODate("2025-06-15T00:00:00.000Z") } }Date ranges use the same lo..hi shorthand. The upper bound gets end-of-day (23:59:59.999Z) when written as a date-only string.
createdAt:2025-01-01..2025-12-31 → $gte 2025-01-01T00:00:00Z, $lte 2025-12-31T23:59:59.999ZcreatedAt:2025-06-01.. → on or after 2025-06-01Relative date expressions
Section titled “Relative date expressions”Evaluated at query time (UTC). Useful for always-fresh filters.
| Expression | Meaning |
|---|---|
now |
Current instant |
today |
Start of current UTC day |
ago(Nd) |
N days ago |
ago(Nw) |
N weeks ago |
ago(Nm) |
N calendar months ago |
ago(Nh) |
N hours ago |
in(Nd) |
N days from now |
in(Nw) |
N weeks from now |
in(Nm) |
N calendar months from now |
in(Nh) |
N hours from now |
createdAt>ago(7d) → created in the last 7 dayscreatedAt>today → created since start of todaycreatedAt:ago(1m)..today → last month up to start of todayexpiresAt<in(7d) → expires within the next 7 daysscheduledAt:now..in(1w) → scheduled between now and 7 days from nowNegation and null
Section titled “Negation and null”-status:deleted → { "status": { "$ne": "deleted" } }email:null → { "email": null }email:exists → { "email": { "$exists": true } }email:!exists → { "email": { "$exists": false } }name:/^john/i → { "name": { "$regex": "^john", "$options": "i" } }Arrays
Section titled “Arrays”tags:[admin,user] → { "tags": { "$in": ["admin", "user"] } }-tags:[spam,bot] → { "tags": { "$nin": ["spam", "bot"] } }comments:size:0 → { "comments": { "$size": 0 } }Nested fields
Section titled “Nested fields”address.city:London → { "address.city": "London" }Projection tokens
Section titled “Projection tokens”Projection tokens are written inline in the same query string.
| Token | Meaning |
|---|---|
+field |
Include field |
-field |
Exclude field (bare, no value) |
Author:Peter +name +email → filter by Author, return only name and emailAuthor:Peter -_id -tags → filter by Author, exclude _id and tags+name +score -_id → projection only, no filterProjection tokens carry through automatically when you switch to BSON mode or the pipeline editor.
Nested paths flatten
Section titled “Nested paths flatten”With any +path token, the columns are exactly _id plus the included paths, in the order you wrote them. A nested path becomes its own column holding the bare value:
+Status +TvContract.Username → columns _id, Status, TvContract.Username+items.sku → items.sku shows ["A-1", "B-2", …], one value per array elementWithout +path tokens the columns are detected from the documents, as before. A trailing 0/1 $project in a pipeline, and an inclusion in BSON mode’s projection field, flatten the same way.
MongoDB rejects a projection that mixes inclusions and exclusions, so - on a column under +path tokens removes that column’s + token instead of adding a - one.
Column picker
Section titled “Column picker”Press c for a list of every field the schema knows, nested paths indented under their parent, each with its type.
| Key | Action |
|---|---|
| typing | Filter the fields (fuzzy, full path) |
↑ / ↓, Ctrl+P / Ctrl+N |
Move |
Space |
Show / hide the field |
Ctrl+A |
Show all filtered fields, or hide them if all are shown |
Ctrl+X |
Hide all filtered fields — then pick the few you want with Space |
Ctrl+R |
Back to the default columns |
Shift+↑ / Shift+↓ |
Move the field one column earlier / later |
Enter |
Apply |
Esc |
Discard changes |
Fields you check become columns in the order you check them, so Ctrl+X followed by a few Spaces gives exactly those columns, in that order. Enter does nothing while no field is checked.
Showing a.b hides a and the other way around, since MongoDB can’t project a path and its parent together.
On Enter the picker writes the shortest projection that shows your choice: nothing for the default columns, -field tokens when only top-level fields are hidden, or a +path list when a nested path or a custom order needs one, or when that list is shorter. The result is in the query bar like any projection you typed. In pipeline mode it edits the pipeline’s $project stage; in BSON mode, use the projection field.
Mark register tokens
Section titled “Mark register tokens”@<letter> resolves to _id: { $in: [...] } from the marks registered for the active collection. The sigil prefix means the token can never collide with a field literally called marks.
@a → docs marked with letter a@a Author:Peter → marked-with-a AND Author=Peter@a +name -_id → marked-with-a, projecting only name@a @b → last-write wins (applies @b)| Detail | Behaviour |
|---|---|
| Single lowercase letter only | @A, @ab, @1 are not recognised |
| Empty register | Resolves to _id: { $in: [] } (matches nothing — explicit, not silent) |
Conflict with _id:... |
Last-write wins, like other field tokens |
| Pipeline editor | @a is expanded to literal ids when opening the pipeline (Ctrl+F / Ctrl+E) |
The token is live in simple mode — newly-marked documents surface on the next reload, because @<letter> is resolved at every query parse. BSON and pipeline modes snapshot the resolved ids at the moment '<letter> is pressed; press it again to refresh.
Type @ in the simple query bar to see every used register in the active collection, with its doc count and color.
See the Usage guide for the full marking workflow.
