MongoDB
MongoDB is a document database. Load collections into MotherDuck with dlt, by exporting newline-delimited JSON, or through a managed change-data-capture connector.
MongoDB stores documents rather than rows, so loading it into MotherDuck is as much a flattening problem as a transfer problem. There is no DuckDB mongodb extension, so collections come across as JSON, either through a tool that handles the schema work or through an export you read yourself.
Load collections with dlt
dlt has a MongoDB source and a MotherDuck destination, and it does the part you'd otherwise write by hand: it infers a schema from the documents, normalizes nested fields into columns and child tables, and evolves the schema as the documents change.
dlt init mongodb motherduck
pip install -r requirements.txt
Set the MongoDB connection string and your MotherDuck token, then run the pipeline:
export MOTHERDUCK_TOKEN="<motherduck_token>"
export SOURCES__MONGODB__CONNECTION_URL="mongodb+srv://<user>:<password>@<cluster>/"
python mongodb_pipeline.py
Configure which collections to load, and whether to load incrementally, in the generated pipeline script. See the dlt MongoDB source documentation for the source options.
Export JSON and read it
For a one-time load or a small collection, export with mongoexport and read the file. The default output is one JSON document per line, which DuckDB reads natively:
mongoexport \
--uri="mongodb+srv://<user>:<password>@<cluster>/<database>" \
--collection=orders \
--out=orders.json
CREATE TABLE orders AS
SELECT * FROM read_json('orders.json', format = 'newline_delimited');
DuckDB infers a schema from a sample of the documents, so nested objects become STRUCT columns and arrays become LIST columns. For a large export, write it to object storage and read from there instead of your local machine:
CREATE TABLE orders AS
SELECT * FROM read_json(
's3://my-bucket/mongo-export/orders/*.json',
format = 'newline_delimited'
);
Use a managed connector
If you want a scheduled sync without writing pipeline code, several MotherDuck ingestion partners list MongoDB as a source: Airbyte, Fivetran, Estuary, and Streamkap. Streamkap and Estuary read MongoDB's change stream, so they suit change-data-capture rather than full reloads.
Things to know
- Extended JSON leaks into your columns.
mongoexportwrites BSON types as wrapper objects, so_idarrives as an object with an$oidkey and dates as objects with a$datekey. Project the values you want out of those wrappers after loading, or restrict the export with--fieldsto skip the types you don't need. dlt handles this conversion for you. - Schema inference samples.
read_jsoninfers types from the first documents it sees, so a field that only appears later, or changes type between documents, can be missed. Pass an explicitcolumnsargument for a stable load, or setunion_by_name = truewhen reading many files. - Flatten before you query. Querying
STRUCTandLISTcolumns works, but downstream BI tools generally expect flat columns. Unnest the fields you report on into a curated table rather than making every consumer walk the document structure. - MongoDB stays the write path. MotherDuck is analytical. Keep application writes in MongoDB and treat MotherDuck as the read side for reporting.