Docs / MongoDB

← Databases

MongoDB

The driver is MongoDB's official Rust driver (with rustls, so no OpenSSL). It opens MongoDB 5.0 and later. The editor takes mongosh syntax, not SQL. The driver is part of the app; nothing is downloaded.

Connect

You pasteRead as
mongodb://user:pass@host:27017/shop?authSource=admin&replicaSet=rs0the URL form; default port 27017
mongodb://a:27017,b:27018/?authSource=admina seed list, kept whole in the Host field
mongodb+srv://user:pass@cluster0.example.net/shopSRV: the hosts come from DNS

What does not fit the form's fields goes in the Database field, after a ?, as connection string options: shop?authSource=admin&replicaSet=rs0, with srv=true for mongodb+srv. The name before the ? is the database statements run in until use changes it (test when empty).

Privileges

The navigator lists databases and collections the login can list, and samples documents to show fields. Nothing else is read for administration: there are no administration tabs. The statements you write need the roles they need.

What works

What does not

Edit documents in the grid

The grid edits the result of a plain find on one collection: the data viewer, or a statement you type, such as db.orders.find({ status: 'paid' }).sort({ _id: 1 }).limit(20). The collection can be named with getCollection("my orders") or db.getSiblingDB("shop").orders. After use, the collection is the one of the database you switched to. A projection is fine when it only lists fields to include and keeps _id. Views, aggregations, findOne, distinct, counts, a projection without _id and a projection that leaves fields out stay read-only.

A document is found by its _id. A result without _id is read-only. Preview SQL shows the mongosh that will run, one statement per document:

Values are written with the BSON type of their column: bool, string, objectId, date, and document and array from the JSON the grid shows. A date is written like 2024-01-02 10:30:00, with or without the time zone (UTC without one). Numbers inside a document or an array keep the type JSON gives them: a whole number is an int (a long beyond 32 bits), a number with a fraction or an exponent a double.

A number keeps the type the document stores, int, long, double or decimal, whenever that type holds the new value exactly: a column's type is only what its documents share (ints and longs make a long column, any of them with doubles a double one), so it does not say what one document holds. An int edited to 7 stays an int, a long a long, a double a double. A value the stored type cannot hold takes the column's type, or the first numeric type that holds it: 3.5 in an int field becomes a double, 3000000000 a long. A long beyond 2^53 is never written as a double, which would lose digits. Nothing is converted on the server: the app only writes the number in the types it knows hold it exactly.

These are refused before anything runs, with the reason:

Each statement must change exactly one document. If one finds none, because the document was deleted or its _id changed since the grid read it, the save stops and says which command.

All or nothing needs a replica set. On a replica set or a sharded cluster, a save runs in a transaction of its own and commits only if every command worked. If you have a transaction open (manual commit), the save runs in it and waits for Commit. If a command fails, MongoDB has no savepoints: the whole transaction is rolled back, with the changes you had not committed yet, and the error says so. On a standalone server there are no transactions: the commands run one after the other, and a failure stops the rest. The commands before it stay saved, and the error says how many.

The undo script that follows a save puts the documents back: $set of the old values for edits, deleteOne for new documents, insertOne of the loaded fields for deleted ones. Lines starting with // say what it cannot restore exactly: fields the result did not show, columns of types the grid cannot write, fields that were NULL (they come back as null, or are left out), and numbers whose type the edit may have changed (they come back as numbers of the type they have then, by the same $switch).

Transactions

Manual commit works on a replica set or a sharded cluster (a mongos); a single-node replica set is enough. On a standalone server it is refused: the Auto-commit button is disabled and says why. A production connection to a replica set opens in manual commit, with Commit and Rollback. The connection keeps one session: the first change after you switch to manual commit, or after a Commit or Rollback, opens a transaction in it (an insert, update or delete, createCollection, createIndex, a save of the grid), and Commit or Rollback ends it. Reads before it open none: they see what is committed, as in autocommit, so browsing data never leaves a transaction open for the server to end after its lifetime. Once a transaction is open, your reads run in it and see its writes; other sessions see them only after Commit.

When the server ends a transaction. MongoDB aborts a transaction that stays open longer than transactionLifetimeLimitSeconds, 60 seconds by default. It also aborts one on some errors: a duplicate key, a write conflict with another session, a statement it refuses in a transaction, a time limit (maxTimeMS) reached. Other errors, such as an unknown pipeline stage, leave it open. After an error PlatypusDB asks the server whether the transaction still exists. When it does not, the statement's or Commit's error says that the server ended the transaction and that its changes were discarded (with the time limit when that was the reason), the transaction shows as closed, and the next statement opens a new one. Cancelling a statement in a transaction rolls the transaction back: the server ends a transaction whose operation is killed, and what the statement did is unknown.

Agents

run_query, sample_rows (find({}).limit(n)) and the rest work with mongosh statements; a statement that is not a plain query is asked about first. Refused on MongoDB: explain, get_er_diagram and query_across_databases; estimate_change answers with a note.

propose_edits proposes documents to insert, update or delete in a collection (not a view): the collection opens in its data viewer with a find of the proposed _ids and the changes pending, which you save or discard as your own edits. A document is named by _id alone; an ObjectId _id is sent as its 24 hexadecimal digits and read as an ObjectId because the collection's _id is one. Values are checked by the rules of the grid's save (see above), before anything opens. Sensitive columns are masked by top-level field only: a sensitive field inside a document is not told apart. See Agents and the CLI.

Known limits

Tested on

The conformance suite runs on MongoDB 5.0 and 8.0: server info, metadata, cancel, abandoned results, errors with their position, fake documents, and values in later documents that differ from the first. Transactions are tested on a single-node replica set of MongoDB 8.0: commit, rollback, reads inside and outside, a result of several batches, metadata in manual commit, and a transaction the server ended for its time limit.

See also: Connecting, Troubleshooting.