From e7dfd134e1804b5fa2338e4c79eeb5681959fd64 Mon Sep 17 00:00:00 2001 From: Guanzhou Song Date: Mon, 3 Aug 2026 07:57:04 -0400 Subject: [PATCH 1/6] Fix 14 documentation links that 404 on documentdb.io Three distinct causes, all confirmed against the live site. Bare sibling links resolve one level too deep. documentdb.io serves pages with a trailing slash, so per RFC 3986 the base for a relative link is the directory .../find/, and a bare target becomes a child of the current page: [insert](insert) on the find page resolves to .../find/insert, not .../insert. Ten links across find, delete, update, insert, and getMore were affected. getMore also needed a different depth for the aggregate link - ../aggregation/aggregate lands in query-and-write/aggregation/, which does not exist. /docs/api-reference does not exist; the reference is served at /docs/reference. Three links used the old path, one in postgres-api/functions.md and two in getting-started/mongo-shell- quickstart.md. The quickstart pair does not currently render - the site shadows that route with hardcoded content - but they go live the moment that override is removed, so they are fixed here too. The .md extension leaks into rendered links. Inline markdown links are not rewritten, so functions.md and %24bucket.md reach the browser verbatim. The $bucketauto links compounded both bugs - leaked extension and wrong depth. Also fixed, same class and found while checking: the Related Topics link in arithmetic-expression/index.md pointed at ../comparison/, but the directory is comparison-query. That file does not currently render either, since api-reference landing pages are generated. Targets carry a trailing slash so they resolve directly rather than through a 301. Every one of the 15 links was verified by resolving it against its rendered page URL and status-checking the result: all 200. Fixes documentdb/documentdb.github.io#126 --- api-reference/commands/query-and-write/delete.md | 4 ++-- api-reference/commands/query-and-write/find.md | 4 ++-- api-reference/commands/query-and-write/getMore.md | 2 +- api-reference/commands/query-and-write/insert.md | 4 ++-- api-reference/commands/query-and-write/update.md | 4 ++-- api-reference/operators/aggregation/$bucketauto.md | 6 +++--- api-reference/operators/arithmetic-expression/index.md | 2 +- getting-started/mongo-shell-quickstart.md | 4 ++-- postgres-api/index.md | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/api-reference/commands/query-and-write/delete.md b/api-reference/commands/query-and-write/delete.md index 6e258f8..a63f808 100644 --- a/api-reference/commands/query-and-write/delete.md +++ b/api-reference/commands/query-and-write/delete.md @@ -172,5 +172,5 @@ db.stores.deleteMany({"promotionEvents.discounts.discountPercentage": 21}, {"lim ## Related content -- [insert with DocumentDB](insert) -- [update with DocumentDB](update) +- [insert with DocumentDB](../insert/) +- [update with DocumentDB](../update/) diff --git a/api-reference/commands/query-and-write/find.md b/api-reference/commands/query-and-write/find.md index c8f3d3f..2013291 100644 --- a/api-reference/commands/query-and-write/find.md +++ b/api-reference/commands/query-and-write/find.md @@ -345,5 +345,5 @@ One of the documents returned shows the specified array elements projected in th ## Related content -- [insert with DocumentDB](insert) -- [update with DocumentDB](update) +- [insert with DocumentDB](../insert/) +- [update with DocumentDB](../update/) diff --git a/api-reference/commands/query-and-write/getMore.md b/api-reference/commands/query-and-write/getMore.md index a7e3008..21eac4e 100644 --- a/api-reference/commands/query-and-write/getMore.md +++ b/api-reference/commands/query-and-write/getMore.md @@ -7,7 +7,7 @@ category: query-and-write # getMore -The `getMore` command is used to retrieve extra batches of documents from an existing cursor. This command is useful when dealing with large datasets that can't be fetched in a single query due to size limitations. The command allows clients to paginate through the results in manageable chunks with commands that return a cursor. For example, [find](./find) and [aggregate](../aggregation/aggregate), to return subsequent batches of documents currently pointed to by the cursor. +The `getMore` command is used to retrieve extra batches of documents from an existing cursor. This command is useful when dealing with large datasets that can't be fetched in a single query due to size limitations. The command allows clients to paginate through the results in manageable chunks with commands that return a cursor. For example, [find](../find/) and [aggregate](../../aggregation/aggregate/), to return subsequent batches of documents currently pointed to by the cursor. ## Syntax diff --git a/api-reference/commands/query-and-write/insert.md b/api-reference/commands/query-and-write/insert.md index 02d409b..a741aa7 100644 --- a/api-reference/commands/query-and-write/insert.md +++ b/api-reference/commands/query-and-write/insert.md @@ -352,5 +352,5 @@ The ordered insert command returns a response confirming the order in which docu ## Related content -- [update with DocumentDB](update) -- [find with DocumentDB](find) +- [update with DocumentDB](../update/) +- [find with DocumentDB](../find/) diff --git a/api-reference/commands/query-and-write/update.md b/api-reference/commands/query-and-write/update.md index 6ca0e77..0736961 100644 --- a/api-reference/commands/query-and-write/update.md +++ b/api-reference/commands/query-and-write/update.md @@ -197,5 +197,5 @@ db.stores.updateOne({"_id": "NonExistentDocId"}, {"$set": {"name": "Lakeshore Re ## Related content -- [insert with DocumentDB](insert) -- [delete with DocumentDB](delete) +- [insert with DocumentDB](../insert/) +- [delete with DocumentDB](../delete/) diff --git a/api-reference/operators/aggregation/$bucketauto.md b/api-reference/operators/aggregation/$bucketauto.md index 3558068..af9ff6f 100644 --- a/api-reference/operators/aggregation/$bucketauto.md +++ b/api-reference/operators/aggregation/$bucketauto.md @@ -7,7 +7,7 @@ category: aggregation # $bucketAuto -The `$bucketAuto` stage categorizes documents into a specified number of buckets, attempting to evenly distribute the documents based on the values of a `groupBy` expression. Unlike [`$bucket`](./%24bucket.md), you do not have to provide boundaries — DocumentDB computes them for you. +The `$bucketAuto` stage categorizes documents into a specified number of buckets, attempting to evenly distribute the documents based on the values of a `groupBy` expression. Unlike [`$bucket`](../%24bucket/), you do not have to provide boundaries — DocumentDB computes them for you. Supported since `v0.105-0`. @@ -117,5 +117,5 @@ Sample output: ## See Also -- [`$bucket`](./%24bucket.md) — fixed-boundary bucketing. -- [`$group`](./%24group.md) — generic grouping by an expression. +- [`$bucket`](../%24bucket/) — fixed-boundary bucketing. +- [`$group`](../%24group/) — generic grouping by an expression. diff --git a/api-reference/operators/arithmetic-expression/index.md b/api-reference/operators/arithmetic-expression/index.md index c44c4a7..45c27cd 100644 --- a/api-reference/operators/arithmetic-expression/index.md +++ b/api-reference/operators/arithmetic-expression/index.md @@ -12,5 +12,5 @@ Arithmetic expression operators perform mathematical operations on numeric value ## Related Topics -- [Comparison Operators](../comparison/) +- [Comparison Operators](../comparison-query/) - [Bitwise Operators](../bitwise/) diff --git a/getting-started/mongo-shell-quickstart.md b/getting-started/mongo-shell-quickstart.md index 69dd1c9..7a29ba5 100644 --- a/getting-started/mongo-shell-quickstart.md +++ b/getting-started/mongo-shell-quickstart.md @@ -182,7 +182,7 @@ db.orders.aggregate([ ]) ``` -DocumentDB also supports stages such as `$lookup`, `$unwind`, `$facet`, `$bucket`, `$bucketAuto`, and many others. See the [API Reference](https://documentdb.io/docs/api-reference) for the full list. +DocumentDB also supports stages such as `$lookup`, `$unwind`, `$facet`, `$bucket`, `$bucketAuto`, and many others. See the [API Reference](https://documentdb.io/docs/reference) for the full list. ## Vector Search @@ -261,6 +261,6 @@ db.runCommand({ rolesInfo: 1 }) ## Next Steps -- Browse the [API Reference](https://documentdb.io/docs/api-reference) for the full list of supported commands, operators, and aggregation stages. +- Browse the [API Reference](https://documentdb.io/docs/reference) for the full list of supported commands, operators, and aggregation stages. - Connect from your application using the [Python](https://documentdb.io/docs/getting-started/python-setup) or [Node.js](https://documentdb.io/docs/getting-started/nodejs-setup) setup guides. - Use the [Visual Studio Code extension](https://documentdb.io/docs/getting-started/vscode-extension-guide) for a GUI experience over the same gateway. diff --git a/postgres-api/index.md b/postgres-api/index.md index 1178355..1ef61e7 100644 --- a/postgres-api/index.md +++ b/postgres-api/index.md @@ -37,7 +37,7 @@ The DocumentDB implementation consists of three PostgreSQL extensions that work ### Usage -To use `pg_documentdb`, you need to have `pg_documentdb_core` installed and configured in your PostgreSQL environment. Once set up, you can leverage the APIs provided by `pg_documentdb` to perform document operations from any PostgreSQL client. For the full list of callable functions, see [Functions](functions.md). +To use `pg_documentdb`, you need to have `pg_documentdb_core` installed and configured in your PostgreSQL environment. Once set up, you can leverage the APIs provided by `pg_documentdb` to perform document operations from any PostgreSQL client. For the full list of callable functions, see [Functions](functions/). ## pg_documentdb_gw From 089a1f3d45e3b714cfd91baecb109259326b906c Mon Sep 17 00:00:00 2001 From: Guanzhou Song Date: Mon, 3 Aug 2026 12:06:40 -0400 Subject: [PATCH 2/6] Use link targets that resolve everywhere, and correct the touched pages against the engine source Follow-up to the previous commit on this branch, addressing review feedback. Link fixes ---------- Switch every corrected inline link to an absolute https://documentdb.io/docs/ target. The previous commit used site-relative forms such as ../insert/ and functions/. Those resolve on the rendered site but 404 in GitHub blob view and in editors, and for postgres-api/index.md and $bucketauto.md that traded a working source link (functions.md, ./%24bucket.md) for a broken one. No single relative form works on both surfaces - GitHub needs insert.md while the site needs ../insert/ - so absolute is the only target that resolves everywhere. This also matches the form commit 2415b71 used for the same class of fix. Fix two links of the same class that the earlier sweep missed: getting-started/python-setup.md:286 - [MongoDB Shell Guide](mongo-shell-quickstart.md) rendered raw and 404s live; the adjacent line 285 was fixed in 2415b71 while this one was left. readme.md:8 - [API Reference](api-reference/index.md) points at a file b6eb41a deleted; the landing page is generated and served at /docs/reference/. Add the trailing slash to the /docs/reference targets this branch introduces, so they resolve directly rather than through a 301, matching the stated style. Delete api-reference/operators/arithmetic-expression/index.md rather than repointing its Related Topics link. The file is never served - the folder URL returns the generated landing page, and /reference/operators/arithmetic-expression/index/ 404s - so the link fix was a no-op. readme.md says api-reference landing pages are generated and index.md files are unnecessary, and this was the last straggler b6eb41a missed when it removed the other twenty. Its "More content to be added" line was also stale: fifteen operators are documented in the folder. The landing description already lives in _metadata.description.md. Content corrections ------------------- Validated the touched pages against the DocumentDB engine and gateway sources. delete.md - deleteMany(filter, {"limit": 1}) was documented as the way to delete one of many matches. limit is a field of the wire-protocol deletes[] element, not a mongosh option, so it is ignored and every match is deleted (delete.c:889 takes the DeleteAllMatchingDocuments branch when limit is 0). Use deleteOne, and document the wire-protocol form separately. Also renumber the duplicated "Example 3" heading. getMore.md - the cursor id must be a BSON int64 (EnsureTopLevelFieldType(..., BSON_TYPE_INT64), bson_aggregation_pipeline.c:3101; the gateway requires as_i64 and rejects anything else with "getMore value should be an i64"), so both examples failed before executing. Wrap them in db.runCommand with NumberLong. An omitted batchSize does not fall back to a small default - aggregation_commands.c:2029 seeds INT_MAX, so the whole remaining cursor is returned, capped only by the 16 MB response limit. The 101 default applies to the first page of find/aggregate only (system_configs.c:152). Document maxTimeMS, which is accepted but was missing. insert.md - the ordered example was not valid JavaScript; the options object's braces were missing. ordered also already defaults to true (insert.c:294), which the parameter table did not say. $bucketauto.md - both worked examples showed output the engine cannot produce. Recomputed from bson_bucket_auto.c: example 1 buckets to {3,18} {18,60} {60,230} with averages 7.67 / 32.67 / 145, since a non-last bucket's max is the next bucket's first value (:780). Example 2 returns three buckets, not four - once a bucket's max is rounded up, following rows below it are absorbed (:732-755); the regression baseline shows the same collapse (bucket_auto.out:213-219: 100 values, buckets:5, POWERSOF2 -> 3 rows). Expand Behavior to cover the distribution rule, the shared boundaries, and the granularity rounding that causes the collapse. mongo-shell-quickstart.md - createUser used role: "readWrite", db: "mydb"; users.c:1448-1471 accepts only readAnyDatabase, readWriteAnyDatabase, and clusterAdmin, and users.c:1479 requires db "admin". createRole inheriting "readWrite" fails the same way. The index block created {email: 1} twice, so the second call collided on the auto-generated name email_1 and the unique index was silently never created (create_indexes.c:4512-4551). Note the documentdb.enableRoleCrud gate, which defaults to off (feature_flag_configs.c:49). postgres-api/index.md - PLAIN/EntraId authentication is rejected by the gateway: auth.rs:357 accepts only SCRAM-SHA-256 and MONGODB-OIDC, and ismaster.rs:69 advertises only SCRAM-SHA-256. MONGODB-OIDC is not a substitute either - it calls documentdb_api_internal.authenticate_token (query_catalog.rs:593), which no SQL in the extensions defines. postgres-api/functions.md - documentdb_api_internal.create_index_background does not exist under that name or schema. The real function is documentdb_api.create_indexes_background(p_database_name text, p_index_spec bson, OUT retval bson, OUT ok boolean, OUT requests bson) (create_index_background--latest.sql:20). update_role is an unconditional error stub (roles.c:190-195). rolesInfo shipped in v0.108-0, not v0.106-0 (CHANGELOG.md:124), and role CRUD is gated behind documentdb.enableRoleCrud. --- .../commands/query-and-write/delete.md | 27 +++++++++++++--- .../commands/query-and-write/find.md | 4 +-- .../commands/query-and-write/getMore.md | 28 ++++++++-------- .../commands/query-and-write/insert.md | 12 +++---- .../commands/query-and-write/update.md | 4 +-- .../operators/aggregation/$bucketauto.md | 32 +++++++++++-------- .../operators/arithmetic-expression/index.md | 16 ---------- getting-started/mongo-shell-quickstart.md | 16 +++++++--- getting-started/python-setup.md | 4 +-- postgres-api/index.md | 4 +-- readme.md | 2 +- 11 files changed, 82 insertions(+), 67 deletions(-) delete mode 100644 api-reference/operators/arithmetic-expression/index.md diff --git a/api-reference/commands/query-and-write/delete.md b/api-reference/commands/query-and-write/delete.md index a63f808..e4bc71c 100644 --- a/api-reference/commands/query-and-write/delete.md +++ b/api-reference/commands/query-and-write/delete.md @@ -161,16 +161,33 @@ db.stores.deleteOne({"_id": "68471088-4d45-4164-ae58-a9428d12f310"}) ### Example 3 - Delete all documents that match a specified query filter ```javascript -db.stores.deleteMany({"promotionEvents.discounts.discountPercentage": 21}, {"limit": 0}) +db.stores.deleteMany({"promotionEvents.discounts.discountPercentage": 21}) ``` -### Example 3 - Delete only one of many documents that match a specified query filter +### Example 4 - Delete only one of many documents that match a specified query filter + +Use `deleteOne` rather than `deleteMany`. There is no shell option that limits `deleteMany` to a single document — `limit` is a field of the wire-protocol `deletes` array element (see below), not a `deleteMany` option, and passing it here has no effect. ```javascript -db.stores.deleteMany({"promotionEvents.discounts.discountPercentage": 21}, {"limit": 1}) +db.stores.deleteOne({"promotionEvents.discounts.discountPercentage": 21}) ``` +## Wire protocol form + +The shell helpers above are wrappers over the `delete` command. Each element of the `deletes` array carries its own `limit`, which must be `0` (delete every match) or `1` (delete at most one match); any other value is rejected with `The limit field in delete objects must be 0 or 1`. + +```javascript +db.runCommand({ + delete: "stores", + deletes: [ + { q: {"promotionEvents.discounts.discountPercentage": 21}, limit: 1 } + ] +}) +``` + +`deleteOne` sends `limit: 1`; `deleteMany` sends `limit: 0`. + ## Related content -- [insert with DocumentDB](../insert/) -- [update with DocumentDB](../update/) +- [insert with DocumentDB](https://documentdb.io/docs/reference/commands/query-and-write/insert/) +- [update with DocumentDB](https://documentdb.io/docs/reference/commands/query-and-write/update/) diff --git a/api-reference/commands/query-and-write/find.md b/api-reference/commands/query-and-write/find.md index 2013291..f8de849 100644 --- a/api-reference/commands/query-and-write/find.md +++ b/api-reference/commands/query-and-write/find.md @@ -345,5 +345,5 @@ One of the documents returned shows the specified array elements projected in th ## Related content -- [insert with DocumentDB](../insert/) -- [update with DocumentDB](../update/) +- [insert with DocumentDB](https://documentdb.io/docs/reference/commands/query-and-write/insert/) +- [update with DocumentDB](https://documentdb.io/docs/reference/commands/query-and-write/update/) diff --git a/api-reference/commands/query-and-write/getMore.md b/api-reference/commands/query-and-write/getMore.md index 21eac4e..e3459d5 100644 --- a/api-reference/commands/query-and-write/getMore.md +++ b/api-reference/commands/query-and-write/getMore.md @@ -7,7 +7,7 @@ category: query-and-write # getMore -The `getMore` command is used to retrieve extra batches of documents from an existing cursor. This command is useful when dealing with large datasets that can't be fetched in a single query due to size limitations. The command allows clients to paginate through the results in manageable chunks with commands that return a cursor. For example, [find](../find/) and [aggregate](../../aggregation/aggregate/), to return subsequent batches of documents currently pointed to by the cursor. +The `getMore` command is used to retrieve extra batches of documents from an existing cursor. This command is useful when dealing with large datasets that can't be fetched in a single query due to size limitations. The command allows clients to paginate through the results in manageable chunks with commands that return a cursor. For example, [find](https://documentdb.io/docs/reference/commands/query-and-write/find/) and [aggregate](https://documentdb.io/docs/reference/commands/aggregation/aggregate/), to return subsequent batches of documents currently pointed to by the cursor. ## Syntax @@ -17,35 +17,37 @@ The syntax for the `getMore` command is as follows: { getMore: , collection: , - batchSize: + batchSize: , + maxTimeMS: } ``` -- `getMore`: The unique identifier for the cursor from which to retrieve more documents. +- `getMore`: The unique identifier for the cursor from which to retrieve more documents. This field must be a BSON 64-bit integer — in `mongosh` write it as `NumberLong("...")`, and in raw BSON as `{"$numberLong": "..."}`. A plain JavaScript number is serialized as a 32-bit integer and is rejected with `BadValue: getMore value should be an i64`. - `collection`: The name of the collection associated with the cursor. -- `batchSize`: (Optional) The number of documents to return in the batch. If not specified, the server uses the default batch size. +- `batchSize`: (Optional) The maximum number of documents to return in the batch. Unlike the first page of `find` or `aggregate`, which defaults to 101 documents, `getMore` has no small default — if `batchSize` is omitted the server returns everything remaining in the cursor, limited only by the 16 MB maximum response size. +- `maxTimeMS`: (Optional) A statement timeout for this batch. On a tailable cursor such as a change stream it instead bounds how long the server waits for new data. ## Examples ### Example 1: Retrieve more documents from a cursor -Assume you have a cursor with the ID `1234567890` from the `stores` collection. The following command retrieves the next batch of documents: +Assume you have a cursor with the ID `1234567890` from the `stores` collection. The following command retrieves the next five documents: ```javascript -{ - getMore: 1234567890, +db.runCommand({ + getMore: NumberLong("1234567890"), collection: "stores", batchSize: 5 -} +}) ``` -### Example 2: Retrieve more documents without specifying batch size +### Example 2: Drain the rest of the cursor -If you don't specify the `batchSize`, the server uses the default batch size: +Omitting `batchSize` returns every document still held by the cursor in a single response, up to the 16 MB response limit: ```javascript -{ - getMore: 1234567890, +db.runCommand({ + getMore: NumberLong("1234567890"), collection: "stores" -} +}) ``` diff --git a/api-reference/commands/query-and-write/insert.md b/api-reference/commands/query-and-write/insert.md index a741aa7..97c4c81 100644 --- a/api-reference/commands/query-and-write/insert.md +++ b/api-reference/commands/query-and-write/insert.md @@ -29,11 +29,11 @@ db.collection.insert( | --- | --- | | **``** | The document or array of documents to insert into the collection| | **`writeConcern`** | (Optional) A document expressing the write concern. The write concern describes the level of acknowledgment requested from the server for the write operation| -| **`ordered`** | (Optional) If `true`, the server inserts the documents in the order provided. If `false`, the server can insert the documents in any order and will attempt to insert all documents regardless of errors| +| **`ordered`** | (Optional) Defaults to `true`. If `true`, the server inserts the documents in the order provided and stops at the first failure. If `false`, the server can insert the documents in any order and will attempt to insert all documents regardless of errors| - ``: The document or array of documents to insert into the collection. - `writeConcern`: Optional. A document expressing the write concern. The write concern describes the level of acknowledgment requested from the server for the write operation. -- `ordered`: Optional. If `true`, the server inserts the documents in the order provided. If `false`, the server can insert the documents in any order and will attempt to insert all documents regardless of errors. +- `ordered`: Optional. Defaults to `true`. If `true`, the server inserts the documents in the order provided and stops at the first failure. If `false`, the server can insert the documents in any order and will attempt to insert all documents regardless of errors. ## Example(s) @@ -237,7 +237,7 @@ If a duplicate value for the _id field is specified, a duplicate key violation e ### Inserting multiple documents in order -Documents that are inserted in bulk can be inserted in order when specifying "ordered": true +Documents inserted in bulk are inserted in the order provided, and the batch stops at the first failure. This is the default, so `ordered: true` below is explicit rather than required. Pass `ordered: false` instead when you want the server to attempt every document regardless of errors. ```javascript db.stores.insertMany([ @@ -335,7 +335,7 @@ db.stores.insertMany([ } ] } -], "ordered": true) +], { ordered: true }) ``` The ordered insert command returns a response confirming the order in which documents were inserted: @@ -352,5 +352,5 @@ The ordered insert command returns a response confirming the order in which docu ## Related content -- [update with DocumentDB](../update/) -- [find with DocumentDB](../find/) +- [update with DocumentDB](https://documentdb.io/docs/reference/commands/query-and-write/update/) +- [find with DocumentDB](https://documentdb.io/docs/reference/commands/query-and-write/find/) diff --git a/api-reference/commands/query-and-write/update.md b/api-reference/commands/query-and-write/update.md index 0736961..7552267 100644 --- a/api-reference/commands/query-and-write/update.md +++ b/api-reference/commands/query-and-write/update.md @@ -197,5 +197,5 @@ db.stores.updateOne({"_id": "NonExistentDocId"}, {"$set": {"name": "Lakeshore Re ## Related content -- [insert with DocumentDB](../insert/) -- [delete with DocumentDB](../delete/) +- [insert with DocumentDB](https://documentdb.io/docs/reference/commands/query-and-write/insert/) +- [delete with DocumentDB](https://documentdb.io/docs/reference/commands/query-and-write/delete/) diff --git a/api-reference/operators/aggregation/$bucketauto.md b/api-reference/operators/aggregation/$bucketauto.md index af9ff6f..090aabd 100644 --- a/api-reference/operators/aggregation/$bucketauto.md +++ b/api-reference/operators/aggregation/$bucketauto.md @@ -7,7 +7,7 @@ category: aggregation # $bucketAuto -The `$bucketAuto` stage categorizes documents into a specified number of buckets, attempting to evenly distribute the documents based on the values of a `groupBy` expression. Unlike [`$bucket`](../%24bucket/), you do not have to provide boundaries — DocumentDB computes them for you. +The `$bucketAuto` stage categorizes documents into a specified number of buckets, attempting to evenly distribute the documents based on the values of a `groupBy` expression. Unlike [`$bucket`](https://documentdb.io/docs/reference/operators/aggregation/%24bucket/), you do not have to provide boundaries — DocumentDB computes them for you. Supported since `v0.105-0`. @@ -39,8 +39,11 @@ Supported since `v0.105-0`. ## Behavior - `$bucketAuto` outputs documents with an `_id` of the form `{ "min": , "max": }`, representing the bucket's lower and upper boundary. The upper boundary is exclusive for all buckets except the last, which includes its upper boundary. -- When the number of distinct `groupBy` values is less than `buckets`, the stage produces fewer buckets than requested. -- When `granularity` is specified, the computed boundaries are rounded outward to the nearest preferred number. +- Without `granularity`, a non-last bucket's `max` is the first `groupBy` value of the *next* bucket, so adjacent buckets share a boundary. The last bucket's `max` is its own largest value. +- Documents are distributed as evenly as the input allows: with `n` documents and `b` buckets each bucket takes `floor(n / b)` documents, and the first `n mod b` buckets take one extra. A bucket is then extended to absorb any following documents that tie with its largest value, so that equal values never straddle a boundary. +- The stage can produce fewer buckets than requested — when the number of distinct `groupBy` values is less than `buckets`, and also whenever `granularity` rounding absorbs documents (see below). +- When `granularity` is specified, the first bucket's `min` is rounded down to the nearest series value strictly below it, and every bucket's `max` is rounded up to the nearest series value strictly above it; each later bucket's `min` is simply the previous bucket's `max`. Because a rounded-up `max` can exceed values that were assigned to later buckets, those documents are pulled into the current bucket, which is why the result often has fewer buckets than requested. Boundaries produced this way are doubles. +- With `granularity`, every `groupBy` value must be numeric and non-negative; a non-numeric value fails with `$bucketAuto only allows specifying a 'granularity' with numeric boundaries`. ## Examples @@ -82,15 +85,17 @@ Sample output: ```json [ - { "_id": { "min": 3, "max": 18 }, "count": 3, "avgPrice": 9.67 }, - { "_id": { "min": 18, "max": 45 }, "count": 3, "avgPrice": 28.33 }, - { "_id": { "min": 45, "max": 230 }, "count": 2, "avgPrice": 145 } + { "_id": { "min": 3, "max": 18 }, "count": 3, "avgPrice": 7.666666666666667 }, + { "_id": { "min": 18, "max": 60 }, "count": 3, "avgPrice": 32.666666666666664 }, + { "_id": { "min": 60, "max": 230 }, "count": 2, "avgPrice": 145 } ] ``` +Eight documents into three buckets gives sizes 3, 3, 2. The buckets hold prices `3, 8, 12`, then `18, 35, 45`, then `60, 230`. Each non-last bucket reports the next bucket's first price as its `max`, so the first bucket ends at `18` and the second at `60`. + ### Example 2: Buckets with rounded boundaries via `granularity` -Group prices into four buckets rounded to a power-of-two series: +Request four buckets rounded to a power-of-two series: ```javascript db.sales.aggregate([ @@ -108,14 +113,15 @@ Sample output: ```json [ - { "_id": { "min": 2, "max": 16 }, "count": 3 }, - { "_id": { "min": 16, "max": 32 }, "count": 1 }, - { "_id": { "min": 32, "max": 64 }, "count": 2 }, - { "_id": { "min": 64, "max": 256 }, "count": 2 } + { "_id": { "min": 2, "max": 16 }, "count": 3 }, + { "_id": { "min": 16, "max": 64 }, "count": 4 }, + { "_id": { "min": 64, "max": 256 }, "count": 1 } ] ``` +Four buckets were requested but three are returned. The even split would have put `3, 8` in the first bucket, but rounding its `max` up from `8` to `16` pulls in `12` as well. The second bucket starts at `18`, and rounding its `max` up from `35` to `64` absorbs `45` and `60`, leaving only `230` for the third bucket. + ## See Also -- [`$bucket`](../%24bucket/) — fixed-boundary bucketing. -- [`$group`](../%24group/) — generic grouping by an expression. +- [`$bucket`](https://documentdb.io/docs/reference/operators/aggregation/%24bucket/) — fixed-boundary bucketing. +- [`$group`](https://documentdb.io/docs/reference/operators/aggregation/%24group/) — generic grouping by an expression. diff --git a/api-reference/operators/arithmetic-expression/index.md b/api-reference/operators/arithmetic-expression/index.md deleted file mode 100644 index 45c27cd..0000000 --- a/api-reference/operators/arithmetic-expression/index.md +++ /dev/null @@ -1,16 +0,0 @@ -# Arithmetic Expressions - -This section contains documentation for arithmetic expression operators. - -## Overview - -Arithmetic expression operators perform mathematical operations on numeric values. - -## Available Operators - -*More content to be added as operators are documented.* - -## Related Topics - -- [Comparison Operators](../comparison-query/) -- [Bitwise Operators](../bitwise/) diff --git a/getting-started/mongo-shell-quickstart.md b/getting-started/mongo-shell-quickstart.md index 7a29ba5..8944f7c 100644 --- a/getting-started/mongo-shell-quickstart.md +++ b/getting-started/mongo-shell-quickstart.md @@ -136,7 +136,7 @@ db.users.createIndex({ email: 1 }) db.users.createIndex({ name: 1, email: 1 }) // Unique index -db.users.createIndex({ email: 1 }, { unique: true }) +db.users.createIndex({ username: 1 }, { unique: true }) // Text index db.articles.createIndex({ content: "text" }) @@ -151,6 +151,8 @@ db.orders.createIndex( ) ``` +When you don't pass a `name`, the index name is generated from its keys — `{ email: 1 }` becomes `email_1`. Creating two indexes on the same keys with different options therefore collides on that generated name and fails with `An existing index has the same name as the requested index`. Give one of them an explicit `name` if you need both. + To create a vector index on an embedding field, use the `cosmosSearchOptions` index spec accepted by the DocumentDB gateway: ```javascript @@ -182,7 +184,7 @@ db.orders.aggregate([ ]) ``` -DocumentDB also supports stages such as `$lookup`, `$unwind`, `$facet`, `$bucket`, `$bucketAuto`, and many others. See the [API Reference](https://documentdb.io/docs/reference) for the full list. +DocumentDB also supports stages such as `$lookup`, `$unwind`, `$facet`, `$bucket`, `$bucketAuto`, and many others. See the [API Reference](https://documentdb.io/docs/reference/) for the full list. ## Vector Search @@ -244,14 +246,18 @@ User and role management commands are also supported: ```javascript // Users -db.runCommand({ createUser: "alice", pwd: "secret", roles: [ { role: "readWrite", db: "mydb" } ] }) +db.runCommand({ createUser: "alice", pwd: "secret", roles: [ { role: "readAnyDatabase", db: "admin" } ] }) db.runCommand({ usersInfo: 1 }) // Roles -db.runCommand({ createRole: "appWriter", privileges: [], roles: [ "readWrite" ] }) +db.runCommand({ createRole: "appReader", privileges: [], roles: [ "readAnyDatabase" ] }) db.runCommand({ rolesInfo: 1 }) ``` +DocumentDB does not implement per-database roles. `createUser` accepts exactly two role sets, both scoped to the `admin` database — `[{ role: "readAnyDatabase", db: "admin" }]` for read-only access, or `[{ role: "clusterAdmin", db: "admin" }, { role: "readWriteAnyDatabase", db: "admin" }]` for read-write access. Anything else, including `readWrite` or a `db` other than `admin`, is rejected. `createRole` inherits from the same set, and `readWriteAnyDatabase` and `clusterAdmin` must be named together. + +The role commands (`createRole`, `dropRole`, `rolesInfo`) are additionally gated behind the `documentdb.enableRoleCrud` GUC, which is `off` by default; `updateRole` is not implemented at all. Turn the GUC on before running the role examples above. + ## Best Practices - **Connection pooling:** reuse a single `mongosh` connection per session. @@ -261,6 +267,6 @@ db.runCommand({ rolesInfo: 1 }) ## Next Steps -- Browse the [API Reference](https://documentdb.io/docs/reference) for the full list of supported commands, operators, and aggregation stages. +- Browse the [API Reference](https://documentdb.io/docs/reference/) for the full list of supported commands, operators, and aggregation stages. - Connect from your application using the [Python](https://documentdb.io/docs/getting-started/python-setup) or [Node.js](https://documentdb.io/docs/getting-started/nodejs-setup) setup guides. - Use the [Visual Studio Code extension](https://documentdb.io/docs/getting-started/vscode-extension-guide) for a GUI experience over the same gateway. diff --git a/getting-started/python-setup.md b/getting-started/python-setup.md index 7ddefcf..30fb888 100644 --- a/getting-started/python-setup.md +++ b/getting-started/python-setup.md @@ -282,5 +282,5 @@ if __name__ == '__main__': ## Next Steps -- Explore advanced features in the [API Reference](https://documentdb.io/docs/reference) -- Check out the [MongoDB Shell Guide](mongo-shell-quickstart.md) for additional query examples +- Explore advanced features in the [API Reference](https://documentdb.io/docs/reference/) +- Check out the [MongoDB Shell Guide](https://documentdb.io/docs/getting-started/mongo-shell-quickstart/) for additional query examples diff --git a/postgres-api/index.md b/postgres-api/index.md index 1ef61e7..4b526e1 100644 --- a/postgres-api/index.md +++ b/postgres-api/index.md @@ -37,7 +37,7 @@ The DocumentDB implementation consists of three PostgreSQL extensions that work ### Usage -To use `pg_documentdb`, you need to have `pg_documentdb_core` installed and configured in your PostgreSQL environment. Once set up, you can leverage the APIs provided by `pg_documentdb` to perform document operations from any PostgreSQL client. For the full list of callable functions, see [Functions](functions/). +To use `pg_documentdb`, you need to have `pg_documentdb_core` installed and configured in your PostgreSQL environment. Once set up, you can leverage the APIs provided by `pg_documentdb` to perform document operations from any PostgreSQL client. For the full list of callable functions, see [Functions](https://documentdb.io/docs/postgres-api/functions/). ## pg_documentdb_gw @@ -47,7 +47,7 @@ To use `pg_documentdb`, you need to have `pg_documentdb_core` installed and conf - **MongoDB Wire Protocol:** Parses MongoDB wire protocol messages (`OP_MSG`, `OP_QUERY`, `OP_INSERT`, etc.) and dispatches them to the corresponding `pg_documentdb` SQL functions. -- **Authentication:** Supports SCRAM-SHA-256 and Plain authentication (including EntraId token-based Plain Auth introduced in v0.106-0). +- **Authentication:** SCRAM-SHA-256. It is the only mechanism advertised in the `hello`/`isMaster` handshake, and the only one usable against a stock build. The gateway also accepts `MONGODB-OIDC` at SASL start for token-based authentication, but that path delegates to a `documentdb_api_internal.authenticate_token` function the extensions do not define, so it requires a deployment-supplied token provider. `PLAIN` is rejected. - **TLS Termination:** Terminates TLS on the gateway port (default `10260`), allowing drivers to connect over the standard MongoDB-style `mongodb://` connection string with `tls=true`. diff --git a/readme.md b/readme.md index 2c49164..a41f8c8 100644 --- a/readme.md +++ b/readme.md @@ -5,7 +5,7 @@ Welcome to the official documentation for [DocumentDB](https://github.com/docume ## Documentation Sections - [Getting Started](getting-started/index.md) - Quick start guides and basic concepts -- [API Reference](api-reference/index.md) - Detailed API documentation +- [API Reference](https://documentdb.io/docs/reference/) - Detailed API documentation - [PostgreSQL API](postgres-api/index.md) - PostgreSQL-compatible API documentation - [Architecture](architecture/index.md) - System architecture and design principles - [documentdb-local](documentdb-local/index.md) - Detailed documentation of the documentdb-local container image From 0f05dfef51bba012f7e2e230aa3aba2450b05daf Mon Sep 17 00:00:00 2001 From: Guanzhou Song Date: Mon, 3 Aug 2026 12:06:41 -0400 Subject: [PATCH 3/6] Fix examples that still fail to run, and reconcile claims across pages Second round of review follow-ups on this branch. Regressions from the previous commit ------------------------------------ mongo-shell-quickstart.md moved the unique index off the colliding email_1 name and onto {username: 1}, but no sample document on the page has a username field. A unique index is not sparse by default - create_indexes.c:6282-6293 sets generateNotFoundTerm for the non-sparse case - so every document missing the path shares one "not found" term and the build fails on the second one. Traded a name collision for a duplicate key violation. Index the plain single-field example on name instead, leaving {email: 1} free for the unique index: three distinct key patterns, all fields present in every sample document, no generated-name collision. Document the sparse caveat too. The role examples were left running against mydb, which the page selects at line 57 and never leaves. roles.c:345 requires the admin database for createRole, dropRole, and rolesInfo, and DEFAULT_ENABLE_ROLES_ADMIN_DB_CHECK is true (feature_flag_configs.c:57), so they fail on a stock build. createUser is not affected - DEFAULT_ENABLE_USERS_ADMIN_DB_CHECK is false - so the page showed user creation succeeding and role creation failing from what looks like the same code. Add "use admin" and say which commands need it. The prose added to explain the role examples described createUser's role documents and then said createRole "inherits from the same set", which reads as the same document form. roles.c:405-410 requires bare strings and rejects anything else with "Invalid inherited from role name provided." The example was already correct; the explanation was not. Also note that createRole requires a privileges field even when empty. The enableRoleCrud note told readers to turn on a GUC without saying how, on a page whose entire audience is in mongosh, where it cannot be set. Give the ALTER SYSTEM form and say it needs psql. Cross-page reconciliation ------------------------- getting-started/index.md:48 still advertised "SCRAM-SHA-256 and Plain" after the previous commit corrected the same claim on postgres-api/index.md. The two sentences share no wording, so fixing one did not surface the other. vscode-extension-guide.md:241 and :247 create {email: 1} and then {email: 1, unique} - the identical email_1 collision diagnosed and fixed in the quickstart, left standing in a sibling guide. Index the plain example on createdAt. Remaining corrections --------------------- getMore.md: the Syntax block still showed a bare "getMore: ", the exact form the parameter list below it says is rejected. Show the runnable db.runCommand/NumberLong shape. Example 1 said it "retrieves the next five documents" while the batchSize bullet calls it a maximum; say "up to five", and warn that a short batch does not mean the cursor is drained - callers must loop until cursor.id is 0. Call the {"$numberLong": ...} form Extended JSON rather than raw BSON, and say where the cursor id comes from. insert.md:341 claimed insertedIds confirms the order documents were inserted. It is keyed by input position and is identical under ordered: false, so it confirms nothing about execution order. functions.md: give the version that introduced the enableRoleCrud gate (v0.108-0) so "supported since v0.106-0" one line above is not read as meaning reachable since v0.106-0, and note the admin-database requirement. $bucketauto.md: the remainder rule said the first n mod b buckets take one extra. The absorb loop decrements the same counter (state->actualRowsLimit++; if (state->remainder > 0) state->remainder--), so granularity absorption consumes spares and the extras do not always land in the earliest buckets. Invisible in both worked examples, where n mod b is 0. --- .../commands/query-and-write/getMore.md | 14 +++++----- .../commands/query-and-write/insert.md | 2 +- .../operators/aggregation/$bucketauto.md | 2 +- getting-started/index.md | 2 +- getting-started/mongo-shell-quickstart.md | 26 ++++++++++++++----- getting-started/vscode-extension-guide.md | 2 +- 6 files changed, 31 insertions(+), 17 deletions(-) diff --git a/api-reference/commands/query-and-write/getMore.md b/api-reference/commands/query-and-write/getMore.md index e3459d5..0a9799c 100644 --- a/api-reference/commands/query-and-write/getMore.md +++ b/api-reference/commands/query-and-write/getMore.md @@ -14,15 +14,15 @@ The `getMore` command is used to retrieve extra batches of documents from an exi The syntax for the `getMore` command is as follows: ```javascript -{ - getMore: , +db.runCommand({ + getMore: NumberLong(""), collection: , batchSize: , maxTimeMS: -} +}) ``` -- `getMore`: The unique identifier for the cursor from which to retrieve more documents. This field must be a BSON 64-bit integer — in `mongosh` write it as `NumberLong("...")`, and in raw BSON as `{"$numberLong": "..."}`. A plain JavaScript number is serialized as a 32-bit integer and is rejected with `BadValue: getMore value should be an i64`. +- `getMore`: The unique identifier for the cursor from which to retrieve more documents, taken from the `cursor.id` field of the originating `find` or `aggregate` response. This field must be a BSON 64-bit integer — in `mongosh` write it as `NumberLong("...")`, and in Extended JSON as `{"$numberLong": "..."}`. A plain JavaScript number is serialized as a 32-bit integer and is rejected with `BadValue: getMore value should be an i64`. - `collection`: The name of the collection associated with the cursor. - `batchSize`: (Optional) The maximum number of documents to return in the batch. Unlike the first page of `find` or `aggregate`, which defaults to 101 documents, `getMore` has no small default — if `batchSize` is omitted the server returns everything remaining in the cursor, limited only by the 16 MB maximum response size. - `maxTimeMS`: (Optional) A statement timeout for this batch. On a tailable cursor such as a change stream it instead bounds how long the server waits for new data. @@ -31,7 +31,7 @@ The syntax for the `getMore` command is as follows: ### Example 1: Retrieve more documents from a cursor -Assume you have a cursor with the ID `1234567890` from the `stores` collection. The following command retrieves the next five documents: +Assume you have a cursor with the ID `1234567890` from the `stores` collection. The following command retrieves up to five more documents: ```javascript db.runCommand({ @@ -43,7 +43,7 @@ db.runCommand({ ### Example 2: Drain the rest of the cursor -Omitting `batchSize` returns every document still held by the cursor in a single response, up to the 16 MB response limit: +Omitting `batchSize` returns every document still held by the cursor in a single response, up to the 16 MB limit: ```javascript db.runCommand({ @@ -51,3 +51,5 @@ db.runCommand({ collection: "stores" }) ``` + +A batch can come back smaller than requested, and an omitted `batchSize` does not guarantee the cursor was drained — the 16 MB limit can cut a batch short. Always keep calling `getMore` until the response reports `cursor.id` of `0`, rather than stopping when a batch is shorter than `batchSize`. diff --git a/api-reference/commands/query-and-write/insert.md b/api-reference/commands/query-and-write/insert.md index 97c4c81..45befbe 100644 --- a/api-reference/commands/query-and-write/insert.md +++ b/api-reference/commands/query-and-write/insert.md @@ -338,7 +338,7 @@ db.stores.insertMany([ ], { ordered: true }) ``` -The ordered insert command returns a response confirming the order in which documents were inserted: +A successful insert returns the ids of the inserted documents, keyed by their position in the input array. Note that `insertedIds` reports input positions, not execution order, so its shape is the same under `ordered: false` — it is not a way to confirm the order in which documents were applied: ```json { diff --git a/api-reference/operators/aggregation/$bucketauto.md b/api-reference/operators/aggregation/$bucketauto.md index 090aabd..cdc8f59 100644 --- a/api-reference/operators/aggregation/$bucketauto.md +++ b/api-reference/operators/aggregation/$bucketauto.md @@ -40,7 +40,7 @@ Supported since `v0.105-0`. - `$bucketAuto` outputs documents with an `_id` of the form `{ "min": , "max": }`, representing the bucket's lower and upper boundary. The upper boundary is exclusive for all buckets except the last, which includes its upper boundary. - Without `granularity`, a non-last bucket's `max` is the first `groupBy` value of the *next* bucket, so adjacent buckets share a boundary. The last bucket's `max` is its own largest value. -- Documents are distributed as evenly as the input allows: with `n` documents and `b` buckets each bucket takes `floor(n / b)` documents, and the first `n mod b` buckets take one extra. A bucket is then extended to absorb any following documents that tie with its largest value, so that equal values never straddle a boundary. +- Documents are distributed as evenly as the input allows: with `n` documents and `b` buckets each bucket takes `floor(n / b)` documents, and a pool of `n mod b` spare documents is handed out one at a time to the buckets that need them, earliest first. A bucket is then extended to absorb any following documents that tie with its largest value, so that equal values never straddle a boundary. Each absorbed document consumes one of the spares, so when `n` is not divisible by `b` the extras do not always land in the earliest buckets. - The stage can produce fewer buckets than requested — when the number of distinct `groupBy` values is less than `buckets`, and also whenever `granularity` rounding absorbs documents (see below). - When `granularity` is specified, the first bucket's `min` is rounded down to the nearest series value strictly below it, and every bucket's `max` is rounded up to the nearest series value strictly above it; each later bucket's `min` is simply the previous bucket's `max`. Because a rounded-up `max` can exceed values that were assigned to later buckets, those documents are pulled into the current bucket, which is why the result often has fewer buckets than requested. Boundaries produced this way are doubles. - With `granularity`, every `groupBy` value must be numeric and non-negative; a non-numeric value fails with `$bucketAuto only allows specifying a 'granularity' with numeric boundaries`. diff --git a/getting-started/index.md b/getting-started/index.md index 3aaf8ea..b72eb83 100644 --- a/getting-started/index.md +++ b/getting-started/index.md @@ -45,7 +45,7 @@ DocumentDB consists of three primary components: 3. **pg_documentdb_gw**: The gateway that: - Implements the MongoDB wire protocol - - Terminates TLS and authenticates clients (SCRAM-SHA-256 and Plain) + - Terminates TLS and authenticates clients (SCRAM-SHA-256) - Translates MongoDB commands into calls against `pg_documentdb` - Manages cursors, sessions, and connection state for MongoDB drivers diff --git a/getting-started/mongo-shell-quickstart.md b/getting-started/mongo-shell-quickstart.md index 8944f7c..0767ff3 100644 --- a/getting-started/mongo-shell-quickstart.md +++ b/getting-started/mongo-shell-quickstart.md @@ -130,13 +130,13 @@ DocumentDB supports many MongoDB-compatible index types, including single-field, ```javascript // Single field index -db.users.createIndex({ email: 1 }) +db.users.createIndex({ name: 1 }) // Compound index db.users.createIndex({ name: 1, email: 1 }) // Unique index -db.users.createIndex({ username: 1 }, { unique: true }) +db.users.createIndex({ email: 1 }, { unique: true }) // Text index db.articles.createIndex({ content: "text" }) @@ -151,7 +151,9 @@ db.orders.createIndex( ) ``` -When you don't pass a `name`, the index name is generated from its keys — `{ email: 1 }` becomes `email_1`. Creating two indexes on the same keys with different options therefore collides on that generated name and fails with `An existing index has the same name as the requested index`. Give one of them an explicit `name` if you need both. +Each index above is on a distinct set of keys, which matters: when you don't pass a `name`, the index name is generated from the keys, so `{ email: 1 }` becomes `email_1` whatever options you give it. Creating both a plain and a unique index on `{ email: 1 }` therefore collides on that one generated name and fails with `An existing index has the same name as the requested index`. Pass an explicit `name` to at least one of them if you need both. + +Note also that a unique index is not sparse unless you say so. Documents that lack the indexed field are all treated as sharing a single "missing" value, so the second such document violates uniqueness. Add `sparse: true` when the field is optional. To create a vector index on an embedding field, use the `cosmosSearchOptions` index spec accepted by the DocumentDB gateway: @@ -244,19 +246,29 @@ db.runCommand({ compact: "users" }) User and role management commands are also supported: +The role commands must be run from the `admin` database, and they are gated behind a server setting that is off by default. Enable it once, as a Postgres superuser, before running the role examples: + +```sql +ALTER SYSTEM SET documentdb.enableRoleCrud = on; +SELECT pg_reload_conf(); +``` + +This is a PostgreSQL GUC, so it cannot be set from `mongosh` — use `psql` or your provider's parameter settings. `updateRole` is not implemented regardless of this setting. + ```javascript -// Users +// Users — can be created from any database db.runCommand({ createUser: "alice", pwd: "secret", roles: [ { role: "readAnyDatabase", db: "admin" } ] }) db.runCommand({ usersInfo: 1 }) -// Roles +// Roles — must be run against admin +use admin db.runCommand({ createRole: "appReader", privileges: [], roles: [ "readAnyDatabase" ] }) db.runCommand({ rolesInfo: 1 }) ``` -DocumentDB does not implement per-database roles. `createUser` accepts exactly two role sets, both scoped to the `admin` database — `[{ role: "readAnyDatabase", db: "admin" }]` for read-only access, or `[{ role: "clusterAdmin", db: "admin" }, { role: "readWriteAnyDatabase", db: "admin" }]` for read-write access. Anything else, including `readWrite` or a `db` other than `admin`, is rejected. `createRole` inherits from the same set, and `readWriteAnyDatabase` and `clusterAdmin` must be named together. +DocumentDB does not implement per-database roles. `createUser` takes role **documents** and accepts exactly two sets, both scoped to `admin` — `[{ role: "readAnyDatabase", db: "admin" }]` for read-only access, or `[{ role: "clusterAdmin", db: "admin" }, { role: "readWriteAnyDatabase", db: "admin" }]` for read-write access. Anything else, including `readWrite` or a `db` other than `admin`, is rejected. -The role commands (`createRole`, `dropRole`, `rolesInfo`) are additionally gated behind the `documentdb.enableRoleCrud` GUC, which is `off` by default; `updateRole` is not implemented at all. Turn the GUC on before running the role examples above. +`createRole` draws on the same three built-in roles but takes their **names as bare strings**, not documents — `roles: [ "readAnyDatabase" ]`. Passing a document there fails with `Invalid inherited from role name provided.` As with `createUser`, `readWriteAnyDatabase` and `clusterAdmin` must be named together. `createRole` also requires a `privileges` field, even when empty. ## Best Practices diff --git a/getting-started/vscode-extension-guide.md b/getting-started/vscode-extension-guide.md index 6af5dfe..4407011 100644 --- a/getting-started/vscode-extension-guide.md +++ b/getting-started/vscode-extension-guide.md @@ -238,7 +238,7 @@ db.collection.getIndexes() #### Creating Indexes ```javascript // Create a single field index -db.collection.createIndex({ "email": 1 }) +db.collection.createIndex({ "createdAt": 1 }) // Create a compound index db.collection.createIndex({ "lastName": 1, "firstName": 1 }) From 835aba1875b6d5c3298f78ee2699ce6bf16307a9 Mon Sep 17 00:00:00 2001 From: Guanzhou Song Date: Mon, 3 Aug 2026 12:22:12 -0400 Subject: [PATCH 4/6] Make the remaining examples runnable, and settle on one URL spelling Third round of review follow-ups. delete.md --------- All four examples plus the wire-protocol snippet filtered on "promotionEvents.discounts.discountPercentage": 21, a value that appears nowhere in the sample document above them - its discounts are 7, 15, 8, 22, 19, 19, 20, 19, 17 and 23. Every one returned deletedCount 0, so the deleteOne-vs-deleteMany distinction that Example 3 and the wire-protocol section exist to demonstrate never actually demonstrated itself. Switch to 19, which the sample document matches three times over. Example 1 also used an _id (68471088-...) that is not the sample document's (0fcc0bf0-...); point it at the real one. Reorder so the destructive example comes last. Previously Example 1 was deleteMany({}), which empties the collection, leaving a reader who works through the page in order unable to tell whether a later zero count meant bad filter syntax, an ignored limit, or an already-empty collection. mongo-shell-quickstart.md ------------------------- The vector index declared dimensions: 384 while the Vector Search example queried the same path with a three-element vector, so running both in order fails on a dimension mismatch. Since the two blocks are separated by the Aggregation Pipelines section, the error is easy to misread as $search syntax. Set the index to 3 to match the query, and note that real embeddings are much wider so nobody takes 3 as a recommendation. Fix the dangling lead-in above the role examples, left over from inserting the GUC prerequisite between it and its code block. URL spelling ------------ The previous commits added trailing slashes to the links they touched, which left the repo spelling the same target two ways - /docs/reference/ in touched files against /docs/reference in the rest - so a future change to the URL base would need two patterns and would silently miss half the links with either one. Normalize every https://documentdb.io/docs/ link to the trailing-slash form. The remaining files are unchanged in substance; the slash only avoids a 301 on the way to the same page. Verified: all 28 external links in the repository resolve, and every documentdb.io/docs link returns 200 directly with no redirect. --- api-reference/commands/diagnostic/hello.md | 2 +- .../commands/query-and-write/delete.md | 24 +++++++++++-------- getting-started/index.md | 12 +++++----- getting-started/mongo-shell-quickstart.md | 16 +++++++------ getting-started/python-setup.md | 2 +- getting-started/vscode-extension-guide.md | 2 +- getting-started/vscode-quickstart.md | 4 ++-- 7 files changed, 34 insertions(+), 28 deletions(-) diff --git a/api-reference/commands/diagnostic/hello.md b/api-reference/commands/diagnostic/hello.md index 1d92590..c261eb1 100644 --- a/api-reference/commands/diagnostic/hello.md +++ b/api-reference/commands/diagnostic/hello.md @@ -105,4 +105,4 @@ The first value is the installed SQL extension version — the schema version, f ## Related content -- [DocumentDB Local](https://documentdb.io/docs/documentdb-local) +- [DocumentDB Local](https://documentdb.io/docs/documentdb-local/) diff --git a/api-reference/commands/query-and-write/delete.md b/api-reference/commands/query-and-write/delete.md index e4bc71c..8b876d3 100644 --- a/api-reference/commands/query-and-write/delete.md +++ b/api-reference/commands/query-and-write/delete.md @@ -146,30 +146,34 @@ Consider this sample document from the stores collection in the StoreData databa } ``` -### Example 1 - Delete all documents in a collection +The sample store above runs two promotion events, and three of its discounts are at 19%, so the filter `"promotionEvents.discounts.discountPercentage": 19` matches it. The examples are ordered so that the destructive one comes last. + +### Example 1 - Delete a document that matches a specified query filter ```javascript -db.stores.deleteMany({}) +db.stores.deleteOne({"_id": "0fcc0bf0-ed18-4ab8-b558-9848e18058f4"}) ``` -### Example 2 - Delete a document that matches a specified query filter +### Example 2 - Delete all documents that match a specified query filter ```javascript -db.stores.deleteOne({"_id": "68471088-4d45-4164-ae58-a9428d12f310"}) +db.stores.deleteMany({"promotionEvents.discounts.discountPercentage": 19}) ``` -### Example 3 - Delete all documents that match a specified query filter +### Example 3 - Delete only one of many documents that match a specified query filter + +Use `deleteOne` rather than `deleteMany`. There is no shell option that limits `deleteMany` to a single document — `limit` is a field of the wire-protocol `deletes` array element (see below), not a `deleteMany` option, and passing it here has no effect. ```javascript -db.stores.deleteMany({"promotionEvents.discounts.discountPercentage": 21}) +db.stores.deleteOne({"promotionEvents.discounts.discountPercentage": 19}) ``` -### Example 4 - Delete only one of many documents that match a specified query filter +### Example 4 - Delete all documents in a collection -Use `deleteOne` rather than `deleteMany`. There is no shell option that limits `deleteMany` to a single document — `limit` is a field of the wire-protocol `deletes` array element (see below), not a `deleteMany` option, and passing it here has no effect. +An empty filter matches everything, so this empties the collection: ```javascript -db.stores.deleteOne({"promotionEvents.discounts.discountPercentage": 21}) +db.stores.deleteMany({}) ``` ## Wire protocol form @@ -180,7 +184,7 @@ The shell helpers above are wrappers over the `delete` command. Each element of db.runCommand({ delete: "stores", deletes: [ - { q: {"promotionEvents.discounts.discountPercentage": 21}, limit: 1 } + { q: {"promotionEvents.discounts.discountPercentage": 19}, limit: 1 } ] }) ``` diff --git a/getting-started/index.md b/getting-started/index.md index b72eb83..f025dbf 100644 --- a/getting-started/index.md +++ b/getting-started/index.md @@ -62,15 +62,15 @@ DocumentDB consists of three primary components: Choose the getting started guide that best fits your needs: ### Quick Start Guides -- [VS Code Extension Quick Start](https://documentdb.io/docs/getting-started/vscode-quickstart) - Recommended for developers new to DocumentDB -- [VS Code Extension Guide](https://documentdb.io/docs/getting-started/vscode-extension-guide) - Comprehensive guide to the VS Code extension +- [VS Code Extension Quick Start](https://documentdb.io/docs/getting-started/vscode-quickstart/) - Recommended for developers new to DocumentDB +- [VS Code Extension Guide](https://documentdb.io/docs/getting-started/vscode-extension-guide/) - Comprehensive guide to the VS Code extension ### Language-Specific Guides -- [Python Setup Guide](https://documentdb.io/docs/getting-started/python-setup) - Using DocumentDB with Python applications -- [Node.js Setup Guide](https://documentdb.io/docs/getting-started/nodejs-setup) - Using DocumentDB with Node.js applications +- [Python Setup Guide](https://documentdb.io/docs/getting-started/python-setup/) - Using DocumentDB with Python applications +- [Node.js Setup Guide](https://documentdb.io/docs/getting-started/nodejs-setup/) - Using DocumentDB with Node.js applications ### Deployment Options -- [Pre-built Packages](https://documentdb.io/docs/getting-started/prebuilt-packages) - Download and install ready-to-use packages +- [Pre-built Packages](https://documentdb.io/docs/getting-started/prebuilt-packages/) - Download and install ready-to-use packages ## Community and Support @@ -86,5 +86,5 @@ Choose the getting started guide that best fits your needs: ## Next Steps After choosing your preferred getting started path: -- Explore our [API Reference](https://documentdb.io/docs/reference) for detailed documentation +- Explore our [API Reference](https://documentdb.io/docs/reference/) for detailed documentation - Join our community to contribute and get support diff --git a/getting-started/mongo-shell-quickstart.md b/getting-started/mongo-shell-quickstart.md index 0767ff3..ccde27a 100644 --- a/getting-started/mongo-shell-quickstart.md +++ b/getting-started/mongo-shell-quickstart.md @@ -46,7 +46,7 @@ DocumentDB Local terminates TLS on the gateway port. The container generates a n mongosh "mongodb://:@localhost:10260/?tls=true&tlsAllowInvalidCertificates=true" ``` -For instructions on installing the generated certificate so you can validate it normally, see [DocumentDB Local](https://documentdb.io/docs/documentdb-local). +For instructions on installing the generated certificate so you can validate it normally, see [DocumentDB Local](https://documentdb.io/docs/documentdb-local/). ## Basic Operations @@ -166,12 +166,14 @@ db.products.createIndex( kind: "vector-ivf", numLists: 100, similarity: "COS", - dimensions: 384 + dimensions: 3 } } ) ``` +`dimensions` must match the length of the vectors you store and query — a query vector of a different length is rejected. Three is used here only to keep the example short; a real embedding field is typically 384, 768, or 1536 wide, depending on the model. + ## Aggregation Pipelines ```javascript @@ -190,6 +192,8 @@ DocumentDB also supports stages such as `$lookup`, `$unwind`, `$facet`, `$bucket ## Vector Search +This queries the `vectorIndex` created above, so the query vector has the same three dimensions the index declares: + ```javascript db.products.aggregate([ { @@ -244,9 +248,7 @@ db.users.validate() db.runCommand({ compact: "users" }) ``` -User and role management commands are also supported: - -The role commands must be run from the `admin` database, and they are gated behind a server setting that is off by default. Enable it once, as a Postgres superuser, before running the role examples: +User and role management commands are also supported, with two caveats specific to roles: they must be run from the `admin` database, and they are gated behind a server setting that is off by default. Enable it once, as a Postgres superuser, before running the role examples: ```sql ALTER SYSTEM SET documentdb.enableRoleCrud = on; @@ -280,5 +282,5 @@ DocumentDB does not implement per-database roles. `createUser` takes role **docu ## Next Steps - Browse the [API Reference](https://documentdb.io/docs/reference/) for the full list of supported commands, operators, and aggregation stages. -- Connect from your application using the [Python](https://documentdb.io/docs/getting-started/python-setup) or [Node.js](https://documentdb.io/docs/getting-started/nodejs-setup) setup guides. -- Use the [Visual Studio Code extension](https://documentdb.io/docs/getting-started/vscode-extension-guide) for a GUI experience over the same gateway. +- Connect from your application using the [Python](https://documentdb.io/docs/getting-started/python-setup/) or [Node.js](https://documentdb.io/docs/getting-started/nodejs-setup/) setup guides. +- Use the [Visual Studio Code extension](https://documentdb.io/docs/getting-started/vscode-extension-guide/) for a GUI experience over the same gateway. diff --git a/getting-started/python-setup.md b/getting-started/python-setup.md index 30fb888..0b4d96f 100644 --- a/getting-started/python-setup.md +++ b/getting-started/python-setup.md @@ -11,7 +11,7 @@ Learn how to set up and use DocumentDB with Python using the official MongoDB Py - Python 3.7+ - pip package manager -- DocumentDB installed and running (see [Pre-built Packages](https://documentdb.io/docs/getting-started/prebuilt-packages)) +- DocumentDB installed and running (see [Pre-built Packages](https://documentdb.io/docs/getting-started/prebuilt-packages/)) - Docker (if DocumentDB is not set up yet) - Git installed (for cloning the repository) diff --git a/getting-started/vscode-extension-guide.md b/getting-started/vscode-extension-guide.md index 4407011..e6eaa71 100644 --- a/getting-started/vscode-extension-guide.md +++ b/getting-started/vscode-extension-guide.md @@ -355,6 +355,6 @@ The VS Code extension is particularly useful for migrating from MongoDB to Docum ## Next Steps -- Learn about [DocumentDB Features](https://documentdb.io/docs/reference) for advanced capabilities +- Learn about [DocumentDB Features](https://documentdb.io/docs/reference/) for advanced capabilities - Join our [Discord community](https://discord.gg/vH7bYu524D) for support and discussions - Report issues and contribute on [GitHub](https://github.com/documentdb/documentdb) diff --git a/getting-started/vscode-quickstart.md b/getting-started/vscode-quickstart.md index c098ad3..2da1b2b 100644 --- a/getting-started/vscode-quickstart.md +++ b/getting-started/vscode-quickstart.md @@ -108,5 +108,5 @@ Get started with DocumentDB using the Visual Studio Code extension for a seamles ## Next Steps -- Explore advanced querying capabilities in the [API Reference](https://documentdb.io/docs/reference) -- Connect your application using the [Python Setup for DocumentDB](https://documentdb.io/docs/getting-started/python-setup) +- Explore advanced querying capabilities in the [API Reference](https://documentdb.io/docs/reference/) +- Connect your application using the [Python Setup for DocumentDB](https://documentdb.io/docs/getting-started/python-setup/) From 563abc6117421395c6414f71dedb0db34655919b Mon Sep 17 00:00:00 2001 From: Guanzhou Song Date: Mon, 3 Aug 2026 12:23:48 -0400 Subject: [PATCH 5/6] Call the 16 MB cap a batch limit, not a response limit BSON_MAX_ALLOWED_SIZE bounds the accumulated batch (cursors.c:1059), while the wire message limit reported by hello is maxMessageSizeBytes at 48000000. Calling the 16 MB figure a maximum response size conflated the two. Also note in delete.md that the examples are independent, since Example 1 removes the sample document the later filters match. --- api-reference/commands/query-and-write/delete.md | 2 +- api-reference/commands/query-and-write/getMore.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api-reference/commands/query-and-write/delete.md b/api-reference/commands/query-and-write/delete.md index 8b876d3..936d13f 100644 --- a/api-reference/commands/query-and-write/delete.md +++ b/api-reference/commands/query-and-write/delete.md @@ -146,7 +146,7 @@ Consider this sample document from the stores collection in the StoreData databa } ``` -The sample store above runs two promotion events, and three of its discounts are at 19%, so the filter `"promotionEvents.discounts.discountPercentage": 19` matches it. The examples are ordered so that the destructive one comes last. +The sample store above runs two promotion events, and three of its discounts are at 19%, so the filter `"promotionEvents.discounts.discountPercentage": 19` matches it. Each example below is independent and assumes the collection is fully populated; they are ordered so that the destructive one comes last. ### Example 1 - Delete a document that matches a specified query filter diff --git a/api-reference/commands/query-and-write/getMore.md b/api-reference/commands/query-and-write/getMore.md index 0a9799c..3a0254d 100644 --- a/api-reference/commands/query-and-write/getMore.md +++ b/api-reference/commands/query-and-write/getMore.md @@ -24,7 +24,7 @@ db.runCommand({ - `getMore`: The unique identifier for the cursor from which to retrieve more documents, taken from the `cursor.id` field of the originating `find` or `aggregate` response. This field must be a BSON 64-bit integer — in `mongosh` write it as `NumberLong("...")`, and in Extended JSON as `{"$numberLong": "..."}`. A plain JavaScript number is serialized as a 32-bit integer and is rejected with `BadValue: getMore value should be an i64`. - `collection`: The name of the collection associated with the cursor. -- `batchSize`: (Optional) The maximum number of documents to return in the batch. Unlike the first page of `find` or `aggregate`, which defaults to 101 documents, `getMore` has no small default — if `batchSize` is omitted the server returns everything remaining in the cursor, limited only by the 16 MB maximum response size. +- `batchSize`: (Optional) The maximum number of documents to return in the batch. Unlike the first page of `find` or `aggregate`, which defaults to 101 documents, `getMore` has no small default — if `batchSize` is omitted the server returns everything remaining in the cursor, stopping only when the accumulated batch reaches 16 MB. - `maxTimeMS`: (Optional) A statement timeout for this batch. On a tailable cursor such as a change stream it instead bounds how long the server waits for new data. ## Examples @@ -43,7 +43,7 @@ db.runCommand({ ### Example 2: Drain the rest of the cursor -Omitting `batchSize` returns every document still held by the cursor in a single response, up to the 16 MB limit: +Omitting `batchSize` returns every document still held by the cursor in a single batch, up to the 16 MB limit: ```javascript db.runCommand({ @@ -52,4 +52,4 @@ db.runCommand({ }) ``` -A batch can come back smaller than requested, and an omitted `batchSize` does not guarantee the cursor was drained — the 16 MB limit can cut a batch short. Always keep calling `getMore` until the response reports `cursor.id` of `0`, rather than stopping when a batch is shorter than `batchSize`. +A batch can come back smaller than requested, and an omitted `batchSize` does not guarantee the cursor was drained — the 16 MB batch limit can cut it short. Always keep calling `getMore` until the response reports a `cursor.id` of `0`, rather than stopping when a batch is shorter than `batchSize`. From 99353cbb6498540cd6cb6119c6f91155ea8ebdeb Mon Sep 17 00:00:00 2001 From: Guanzhou Song Date: Mon, 3 Aug 2026 12:27:06 -0400 Subject: [PATCH 6/6] Re-apply the functions.md corrections that survive PR #58 PR #58 landed on main while this branch was open and rewrote postgres-api/functions.md against v0.114-0. Its version supersedes this branch's edits to that file, including on one point where it is right and this branch was wrong: create_indexes_background does not wait for builds to finish. The SQL COMMENT ON says it does, which is where the earlier claim here came from, but the C implementation runs one SPI query and returns. Took #58's file wholesale during the rebase. Three things it did not cover are restored on top of it: The API Reference link at the bottom of the page is back to https://documentdb.io/docs/api-reference, which 404s - #58 branched from before this PR's fix, so the rewrite reintroduced it. This is the same cause 2 the PR documents. update_role is still described as "Updates an existing role's privileges or inherited roles." Its body is a bare ereport(ERROR) (roles.c:190-195) with no EnableRoleCrud guard, so every call raises regardless of spec or flag. Neither documentdb.enableRoleCrud nor documentdb.enableRolesAdminDBCheck was mentioned, so the page read as though the role functions work out of the box when the first is off by default and the second is on. configuration.md gains both flags. They do not belong in the existing off-by-default table, whose preamble scopes it to flags that fail silently - these raise - so they get their own subsection. Defaults confirmed at feature_flag_configs.c:49, 57 and 53. --- postgres-api/configuration.md | 9 +++++++++ postgres-api/functions.md | 6 ++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/postgres-api/configuration.md b/postgres-api/configuration.md index 94c0a1b..a5a2106 100644 --- a/postgres-api/configuration.md +++ b/postgres-api/configuration.md @@ -37,6 +37,15 @@ These flags gate functionality that is otherwise silently unavailable — in eac | `documentdb.enablePreImages` | `off` | Allows the `changeStreamPreAndPostImages` collection option. While `off`, `create` and `collMod` reject that option. | | `documentdb.indexBuildsScheduledOnBgWorker` | `off` | Drains the background index build queue from a PostgreSQL background worker instead of a pg_cron job. Leave `off` where pg_cron is configured and working; turn it on where pg_cron cannot run the job, otherwise queued index builds never start. | +### Role management flags + +Unlike the flags above, these two produce an error rather than a missing effect, so a caller sees the failure immediately. + +| GUC | Default | Description | +| --- | --- | --- | +| `documentdb.enableRoleCrud` | `off` (since v0.108-0) | Enables role CRUD through the data plane. While `off`, `create_role`, `drop_role`, and `roles_info` each raise before doing any work, for example "The CreateRole command is currently unsupported." Note that `update_role` is not implemented in any case. | +| `documentdb.enableRolesAdminDBCheck` | `on` (since v0.109-0) | Requires the wire-protocol role commands to be issued against the `admin` database, raising "CreateRole must be called from 'admin' database." otherwise. The user management commands are governed separately by `documentdb.enableUsersAdminDBCheck`, which is `off` by default. | + ## Gateway configuration The gateway (`pg_documentdb_gw`) reads its settings from a JSON configuration file and/or `DOCUMENTDB_*` environment variables. Environment variables override the JSON file, which makes them convenient for systemd-managed and container deployments. *(Environment-variable configuration added in v0.114-0.)* diff --git a/postgres-api/functions.md b/postgres-api/functions.md index cdb1514..83caddc 100644 --- a/postgres-api/functions.md +++ b/postgres-api/functions.md @@ -160,11 +160,13 @@ Functions for creating, updating, and managing database users. Backed by the wir All four role functions were added in v0.106-0, together with wire-protocol support for `createRole`. Support for the `dropRole` and `rolesInfo` commands followed in v0.108-0. `updateRole` is routed by the gateway to `documentdb_api.update_role`. +All of them are gated behind `documentdb.enableRoleCrud`, added in v0.108-0 and off by default, so on a stock build `create_role`, `drop_role`, and `roles_info` raise "The CreateRole command is currently unsupported." and its equivalents before doing any work. The wire-protocol commands are additionally required to run against the `admin` database (`documentdb.enableRolesAdminDBCheck`, on by default since v0.109-0); the user management functions above are not. + | Function | Description | | --- | --- | | `documentdb_api.create_role(p_spec bson)` | Creates a new role. | | `documentdb_api.drop_role(p_spec bson)` | Drops an existing role. | -| `documentdb_api.update_role(p_spec bson)` | Updates an existing role's privileges or inherited roles. | +| `documentdb_api.update_role(p_spec bson)` | Not implemented. The function body is a bare `ereport(ERROR)`, so every call raises "UpdateRole command is not supported in preview." regardless of the spec or of `enableRoleCrud`. | | `documentdb_api.roles_info(p_spec bson)` | Returns information about one or more roles. | ## Utility Functions @@ -187,4 +189,4 @@ SELECT * FROM documentdb_api.insert( Because `insert` declares two `OUT` parameters, `SELECT *` returns them as the named columns `p_result` and `p_success`. Dropping the `*` would collapse them into a single composite value. -For more complete examples (cursors, aggregation, sharding) see the [API Reference](https://documentdb.io/docs/api-reference). +For more complete examples (cursors, aggregation, sharding) see the [API Reference](https://documentdb.io/docs/reference/).