> ## Documentation Index
> Fetch the complete documentation index at: https://ngquct-docs-fix-500-query-results.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# MongoDB

> Connect to MongoDB with MQL shell queries, collection browsing, and automatic Atlas SRV setup

export const name_0 = "MongoDB"

export const plugin_0 = "MongoDB Driver"

Filters and pipelines are parsed as JSON and Extended JSON, never as JavaScript, so every key needs quoting, operators included: `{age: {$gte: 18}}` fails with a parse error. Collections appear as tables in the sidebar, with top-level fields as columns and nested objects as formatted JSON.

The {name_0} driver is not in the app. Picking {name_0} in the **Choose a Database** sheet offers the
download before the form opens, and opening a saved {name_0} connection installs it without asking.
**Settings > Plugins > Browse > {plugin_0}** installs it up front. See [Plugins](/features/plugins).

## Quick setup

<Steps>
  <Step title="Create Connection">
    Click **Create Connection…**, select **MongoDB**, and enter hosts and credentials
  </Step>

  <Step title="Test Connection">
    Click **Test Connection** to verify, then **Save & Connect**
  </Step>
</Steps>

## Connection settings

| Field              | Default           | Notes                                                                |
| ------------------ | ----------------- | -------------------------------------------------------------------- |
| **Hosts**          | `localhost:27017` | Several `host:port` pairs for a replica set                          |
| **Username**       | -                 | Leave empty for local dev without auth                               |
| **Password**       | -                 |                                                                      |
| **Database**       | -                 | Opens straight into that database. Leave it empty to browse them all |
| **Auth Database**  | -                 | Advanced. Where your user account lives, usually `admin`             |
| **Auth Mechanism** | Default           | SCRAM-SHA-1, SCRAM-SHA-256, X.509, or AWS IAM, under Authentication  |

Naming a **Database** skips listing every database on the server, which is worth doing on a cluster with hundreds. Leave it empty and the first non-system database opens instead. `Cmd+K` switches either way, on the same connection, with no reconnect.

**Auth Database** is a separate question: it says where your account is defined, not what you browse. Left empty, it follows the **Database** field. An account defined in `admin` needs **Auth Database** set to `admin` whenever **Database** names something else, or authentication fails. SRV connections authenticate against `admin` regardless, unless told otherwise. Switching databases in the app never changes it, so browsing a database your user has no account in is fine.

Also in Advanced: **Read Preference**, **Write Concern**, **Use SRV Record**, **Replica Set** name, and **Legacy UUID Encoding**. There is no minimum server version; the driver adapts what it asks for to what the server answers.

<Frame caption="MongoDB connection form">
  <img className="block dark:hidden" src="https://mintcdn.com/ngquct-docs-fix-500-query-results/HJY892UtvXUv1PFn/images/mongodb-connection-form.png?fit=max&auto=format&n=HJY892UtvXUv1PFn&q=85&s=1f2c3ac966a93533e9da9b512b0a309b" alt="MongoDB connection form with the multi-host Hosts editor" width="1560" height="960" data-path="images/mongodb-connection-form.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/ngquct-docs-fix-500-query-results/HJY892UtvXUv1PFn/images/mongodb-connection-form-dark.png?fit=max&auto=format&n=HJY892UtvXUv1PFn&q=85&s=da405e7984b31c0e6962f8d836ec20b2" alt="MongoDB connection form with the multi-host Hosts editor" width="1560" height="960" data-path="images/mongodb-connection-form-dark.png" />
</Frame>

On MongoDB 4.0 and later the database list is requested as authorized databases only, so an account without the `listDatabases` privilege still sees what it can read. On an older server that list comes back empty: name a **Database** on the connection instead.

## Connection URL

```text theme={null}
mongodb://user:password@host:27017/database?authSource=admin
mongodb+srv://user:password@cluster.mongodb.net/database
```

`mongodb+srv://` resolves hosts through DNS SRV records and takes no port; one pasted into the field is stripped before connecting. Plain `mongodb://` keeps whatever port you give it. See [Connection URL Reference](/connections/urls).

## MongoDB Atlas (SRV)

An Atlas connection needs the cluster hostname, a username, and a password. Atlas requires SRV and TLS, so a host ending in `.mongodb.net` gets both turned on for you, TLS only if the SSL mode was still Disabled. Elsewhere the **Use SRV Record** toggle in Advanced does the same job. Add your current IP to the cluster's access list in the Atlas console first: traffic from an address that is not on it times out rather than failing.

## Replica sets

The **Hosts** field takes comma-separated pairs (`host1:27017,host2:27017,host3:27017`), the primary is discovered, and writes are routed to it. Set the replica set name in Advanced. A multi-host URI pastes in directly:

```text theme={null}
mongodb://user:pass@host1:27017,host2:27017,host3:27017/db?replicaSet=rs0
```

<Warning>
  <Warning>
    Over an SSH tunnel only the first host is used and the rest of the list is dropped. Replica set discovery and failover are off for that session, with nothing on screen to say so.
  </Warning>
</Warning>

## Browsing collections

Click a collection to page through its documents. Column layout is inferred by sampling documents, not read from a validator, so a field missing from the sample gets no column. ObjectIds render as strings, arrays and nested objects as formatted JSON.

The filter bar's column picker lists paths inside nested objects and arrays of objects, so `customer.country` and `items.sku` filter directly; a row on an array field chooses **any element** or **same element**, which makes one array entry satisfy every row set to it. See [Filtering](/features/filtering#nested-fields). A field name containing a literal dot is left out of the picker, since MongoDB reads a dot as a path separator; reach it with `$getField` inside `$expr`.

The Structure tab lists a collection's indexes; create and drop them from a query tab with `db.users.createIndex({"email": 1})` and `db.users.dropIndex("email_1")`. **New Database** asks for a database name and a first collection, both required. **New View** opens a query tab holding a `db.createView("view_name", "source_collection", [pipeline])` template, and editing a view pre-fills `db.runCommand({"collMod": …})`.

### Binary UUIDs

A binary subtype 4 field renders as `UUID("8cd003eb-4a25-4324-9332-88fce2da0d1a")`. Subtype 3 is the legacy format, and its bytes do not say which driver wrote them, so it stays `BinData(3, "…")` until **Legacy UUID Encoding** on the connection is set to Java, C#, or Python. Match it to the driver that wrote the data: the wrong choice shows a valid-looking but wrong UUID.

Once set, the value renders as `LegacyJavaUUID("…")` and reads that way everywhere, filters and MQL export included. Nothing stored is rewritten, `uuidRepresentation=javaLegacy` in a pasted URL sets the same option, and a change takes effect on the next connect.

## Writing MQL

Every key is quoted, and the editor has no comment syntax, so a `//` line becomes part of the statement. Value constructors are translated, so a value copied out of the grid pastes straight into a filter: `ObjectId`, `ISODate`, `Date`, `NumberInt`, `NumberLong`, `NumberDecimal`, `Timestamp`, `BinData`, `HexData`, `MinKey`, `MaxKey`, `UUID`, and the legacy UUID names. Anything else JavaScript, including `new Date()`, arithmetic, and regex literals such as `/abc/i`, is not evaluated.

```javascript theme={null}
db.orders.find(
  {"status": "completed"},
  {"customerId": 1, "total": 1}
).sort({"date": -1}).limit(20)

db.sales.aggregate([
  {"$match": {"date": {"$gte": {"$date": "2025-01-01T00:00:00Z"}}}},
  {"$group": {"_id": "$product", "totalSales": {"$sum": "$amount"}}}
])
```

### Collection references

`db.users`, `db["users"]`, or `db.getCollection("users")`. The last two take the name exactly as written, so use them for names with dots or spaces, names starting with a digit, and names that collide with a database method such as `stats`.

### Chained methods

`.sort()`, `.limit()` and `.skip()` chain onto `find` and onto `aggregate`, where they become `$sort`, `$skip` and `$limit` stages appended in that order. Chaining onto something that returns no cursor, such as `insertOne`, is an error, as is a method the parser does not know.

### Write options

`updateOne`, `updateMany`, `replaceOne` and `findOneAndUpdate` take a third options document, and `upsert`, `arrayFilters` and `hint` reach the server. The result reports `modifiedCount` and `upsertedCount`.

```javascript theme={null}
db.users.updateOne({_id: 1}, {"$set": {"active": true}}, {"upsert": true})
```

### Supported methods

Collection-level `find`, `findOne`, `aggregate`, `countDocuments`/`count`, `insertOne`/`insertMany`, `updateOne`/`updateMany`, `replaceOne`, `deleteOne`/`deleteMany`, `findOneAndUpdate`/`findOneAndReplace`/`findOneAndDelete`, `createIndex`, `dropIndex`, `drop`; database-level `getCollectionNames`/`listCollections`, `createCollection`, `dropDatabase`, `version`, `stats`. Anything else goes through `db.runCommand({…})` or `db.adminCommand({…})`. An unlisted shell method such as `distinct` or `getUsers` returns an unsupported-method error.

`Cmd+Option+E` explains a statement, converting `find`, `aggregate`, `countDocuments`, update, delete, and `findOneAnd*` calls into `db.runCommand({"explain": …, "verbosity": "executionStats"})`. `Cmd+Shift+F` reformats by nesting depth. Autocomplete offers collections, methods, nested field paths such as `address.city`, and the `$` operators valid at the cursor; see [Autocomplete](/features/autocomplete#mongodb).

## SSL/TLS

New connections default to **Disabled**, and the driver has no TLS fallback: **Preferred** behaves exactly as **Required**, which is what the SSL pane warns about. For an unencrypted local instance use **Disabled** or [SSH tunneling](/connections/ssh-tunneling). See [SSL/TLS](/connections/ssl).

## Limitations

* A row with no `_id` cannot be updated or deleted. The save is skipped rather than matched on the remaining fields. Keep `_id` in the projection so every row carries one.
* `_id` is read-only in the grid, and left out of an insert entirely so the server generates it. To choose your own, insert with `db.collection.insertOne({…})`.
* Transactions are not exposed. Statements always run standalone, on any topology.
* Nested paths filter but do not sort. Sorting works on the grid's own columns.
* **same element** covers a field one array deep. A path through an array inside another array needs nested `$elemMatch`, so those filter with dot notation only.
* GridFS buckets are not browsable, and change streams are unsupported.
* `db.getSiblingDB(…)` is not supported. A query runs against the database the connection is on; switch with `Cmd+K`.

## Troubleshooting

**Connection refused**: check MongoDB is running (`brew services start mongodb-community`) and that the port and `bindIp` in `mongod.conf` match what you entered.

**Authentication fails on connect**: the error names the database that was authenticated against. If your user does not live there, set **Auth Database** in Advanced; otherwise check the username, password, and auth mechanism. The MQL editor does not parse `db.getUsers()` or `db.createUser()`; read users with `db.runCommand({"usersInfo": 1})`.

**Timeout**: for Atlas, add your IP to the cluster's access list first. Otherwise verify host and port and check the network and firewall.

**A collection is slow to open**: a sort or filter on an unindexed field makes MongoDB read every document, even for 20 rows. Check the Structure tab for an index on that field. `Cmd+.` stops the query on the server.

**The row total shows `~`**: that is the instant estimate from collection metadata. The automatic count is capped at 5 seconds and keeps the estimate if the server is slower; **Count Exactly** runs a real count against your query timeout. Views and time-series collections have no metadata count, so their estimate can be missing altogether.
