@antelopejs/mongodb
The MongoDB backend of AntelopeJS. It runs the queries of the database interface on MongoDB with the official mongodb driver, and gives that driver's client to modules that need it directly.
Part of AntelopeJS. Used by AntelopeJS DMS, the open-source back office for your PostgreSQL, MongoDB or RethinkDB database.
Interfaces
| Interface | Documentation |
|---|---|
@antelopejs/interface-database | Database |
@antelopejs/interface-mongodb | MongoDB |
@antelopejs/interface-database-catalog | External mode |
The database interface pages document schemas, tables, queries, change feeds, and atomic mutations.
Install
ajs project modules add @antelopejs/mongodb
The command writes the default configuration of the module. It connects to mongodb://localhost:27017 and uses the database antelopejs.
Configuration
import { defineConfig } from "@antelopejs/interface-core/config";
export default defineConfig({
name: "my-project",
modules: {
mongodb: {
source: {
type: "package",
package: "@antelopejs/mongodb",
version: "^1.4.2",
},
config: {
url: "mongodb://localhost:27017/?replicaSet=rs0",
database: "my-project",
options: { maxPoolSize: 10 },
},
},
},
envOverrides: {
MONGODB_URL: "modules.mongodb.config.url",
},
});
| Key | Description |
|---|---|
url | MongoDB connection string. |
database | The database that holds the collections of every schema. |
options | Optional MongoClientOptions that the module passes to the driver. |
mode | owned (the default) or external. An owned instance creates its own collections and scopes them to instances. An external instance serves a database it did not create. See External mode. |
statementTimeoutMs | Optional server-side time limit of each read and write of an external instance, sent as maxTimeMS. It must be a positive safe integer. |
catalog | { enabled?: boolean }. Sets whether an external instance answers the catalog outside development. |
An external instance requires a non-empty url and database. It reads and writes the documents of the client's own collections and never changes their structure. See External mode.
Change feeds use MongoDB change streams, which need a replica set. A single-node replica set is enough in development.
Quick start
In the module that stores data, add the database interface:
pnpm add @antelopejs/interface-database
Then follow the database interface guide to declare a schema and query it. The same code runs on @antelopejs/postgres and @antelopejs/rethinkdb.
To call the driver directly instead, add @antelopejs/interface-mongodb:
import { GetClient } from "@antelopejs/interface-mongodb";
const client = await GetClient();
const users = client.db("my-project").collection("users");
Storage layout
- Each schema table is one collection,
<schemaId>__<table>, that every instance of the schema shares. Each document stores its instance in_instance. _idis unique across instances, so use globally unique record identities.- Each declared index
<name>becomes a MongoDB index<name>__iwhose first field is_instance. An index declared withcrossInstance: truealso gets an index<name>without the prefix, forCROSS_INSTANCEqueries. Without it, those queries still work, but they cannot use an index and log a warning once per index. - An index declared with
unique: truemakes its<name>__iindex unique, so a key is unique per instance. The cross-instance index is never unique. A change of the flag rebuilds the index. The creation of a unique index fails while the instance holds duplicates. Schema initialization then logs the error and retries until you remove them. - When MongoDB refuses a write for a duplicate key (code 11000), on
_idor on a unique index, the module throws theDuplicateKeyErrorof the interface with the declared index name and fields. - Atomic mutations use a second client with
retryWritesandretryReadsturned off.
Schema initialization drops an index only in two cases. The index has the name the module gives a declared index in MongoDB (<name>__i, or <name> for a cross-instance index) but other fields or another uniqueness. Or the index has the fields of such an index but another uniqueness. Any other index stays, such as an index <name> that leads with the declared field instead of _instance. To remove an index that no schema declares, drop it by hand, for example db.getCollection("<schemaId>__<table>").dropIndex("<name>").
Documentation
- Database documents the
@antelopejs/interface-databasecontract that this module implements. - MongoDB documents the
@antelopejs/interface-mongodbcontract that this module implements. - External mode explains how the module serves a database it did not create, and its catalog.
- Configuration documents module sources,
configblocks, and config variables inantelope.config.ts.
Compatibility
| Package | Supported | Tested with |
|---|---|---|
@antelopejs/interface-core | >=0.2.4 <1.0.0 | 0.2.4 |
@antelopejs/interface-database | >=0.3.0 <0.4.0 | 0.3.0 |
@antelopejs/interface-database-catalog | >=0.0.3 <0.1.0 | 0.0.3 |
@antelopejs/interface-mongodb | >=0.0.6 <1.0.0 | 0.0.6 |
.nvmrc sets the Node.js release for development. The dependencies of package.json set the range of the mongodb driver. MONGODB_VERSION in src/test/antelope.test.ts sets the MongoDB server release of the test replica set.
Contributing
pnpm install
pnpm lint
pnpm format:check
pnpm knip
pnpm test # build, then run the owned and external suites against an in-memory replica set
The tests start MongoDB with mongodb-memory-server, which downloads the server binary on the first run. They also run the shared conformance suite of @antelopejs/interface-database.
Read the contribution guidelines before you open a pull request.