Maintainers
Pricing
Enterprise
More
More
Documentation
Try Live
Rankings
Install
Blog
Docs7
Ask
New
Add Docs
Elixir MongoDB Driver
https://github.com/zookzook/elixir-mongodb-driver
Admin
MongoDB driver for Elixir
Tokens:
11,970
Snippets:
72
Trust Score:
8.7
License:
Apache-2.0
Update:
1 year ago
Context
Chat
Benchmark
90
Latest
Show doc for...
Code
Info
Show Results
Tokens:
Raw
Copy
Link
Tokens:
Raw
Copy
Link
### Phoenix Server Setup and Start Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/insights/README.md Commands to install project dependencies, create and migrate the database, and start the Phoenix server. These commands are executed using the Mix build tool and IEx. ```shell mix deps.get ``` ```shell mix ecto.setup ``` ```shell mix phx.server ``` ```shell iex -S mix phx.server ``` -------------------------------- ### Dockerfile Migration Execution Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Example Dockerfile entrypoint that runs migrations before starting the application server. ```dockerfile ENTRYPOINT /app/bin/migrate && /app/bin/server ``` -------------------------------- ### Setup MongoDB Replica Set for Testing with mtools Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Outlines the steps to set up a MongoDB replica set for testing using `mtools`. This includes installing dependencies, configuring the path, and initializing a replica set for testing purposes. ```bash pyenv global 3.6 pip3 install --upgrade pip pip3 install 'mtools[all]' export PATH=to-your-mongodb/bin/:$PATH ulimit -S -n 2048 ## in case of Mac OS X mlaunch init --setParameter enableTestCommands=1 --replicaset --name "rs_1" mongosh --host localhost:27017 --eval 'rs.initiate({_id: "rs_1", members: [{_id: 0, host: "127.0.0.1:27017"}, {_id: 1, host: "127.0.0.1:27018"}, {_id: 2, host: "127.0.0.1:27019"}]})' mix test --exclude ssl --exclude socket ``` -------------------------------- ### Release Overlay Script Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Example shell script for an Elixir release overlay to run migrations before starting the application server. ```shell #!/bin/sh cd -P -- "$(dirname -- "$0")" exec ./my_app eval MyApp.Release.migrate ``` ```shell #!/bin/sh cd -P -- "$(dirname -- "$0")" PHX_SERVER=true exec ./my_app start ``` -------------------------------- ### Install mongodb_driver Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Instructions for adding the mongodb_driver dependency to your Elixir project's `mix.exs` file and fetching it. ```elixir defp deps do [{:mongodb_driver, "~> 1.5.0"}] end ``` -------------------------------- ### Example Migration Script Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md An example of an Elixir migration script defining `up` and `down` functions to manage database indexes. The `up` function applies changes, and the `down` function reverts them. ```elixir defmodule Mongo.Migrations.AddIndexes do def up() do indexes = [ [key: [email: 1], name: "email_index", unique: true] ] Mongo.create_indexes(:my_db, "my_collection", indexes) end def down() do Mongo.drop_index(:my_db, "my_collection", "email_index") end end ``` -------------------------------- ### Start Multiple MongoDB Topologies Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Demonstrates how to initiate multiple MongoDB connections using `Mongo.start_link` with distinct names and URLs. This allows the driver to manage different database configurations or environments concurrently. ```elixir Mongo.start_link(name: :topology_1, url: "mongodb://localhost:27017/mig_test_1", timeout: 60_000, pool_size: 5, idle_interval: 10_000) Mongo.start_link(name: :topology_2, url: "mongodb://localhost:27017/mig_test_2", timeout: 60_000, pool_size: 5, idle_interval: 10_000) ``` -------------------------------- ### Start Pooled Connection Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Initiates a MongoDB connection with pooling enabled using the `:pool_size` option in `Mongo.start_link`. This allows managing multiple connections efficiently. ```elixir {:ok, top} = Mongo.start_link(url: "mongodb://localhost:27017/db-name", pool_size: 3) ``` -------------------------------- ### Start MongoDB Command Event Handler Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Demonstrates how to set up command monitoring for the Elixir MongoDB driver. It starts the `Mongo.EventHandler` to log command events and then performs a `find_one` operation to show the logged events. ```elixir iex> Mongo.EventHandler.start() iex> {:ok, top} = Mongo.start_link(url: "mongodb://localhost:27017/test") {:ok, #PID<0.226.0>} iex> Mongo.find_one(top, "test", %{}) |> Enum.to_list() [info] Received command: %Mongo.Events.CommandStartedEvent{command: [find: "test", ... [info] Received command: %Mongo.Events.CommandSucceededEvent{command_name: :find, ... ``` -------------------------------- ### Connect to MongoDB (Unpooled) Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Demonstrates how to start an unpooled connection to a MongoDB instance using `Mongo.start_link` and perform a basic find operation. It also shows how failing operations return a `{:error, Mongo.Error}` tuple. ```elixir # Starts an unpooled connection {:ok, top} = Mongo.start_link(url: "mongodb://localhost:27017/my-database") top |> Mongo.find("test-collection", %{}) |> Enum.to_list() ``` ```elixir { :error, %Mongo.Error{ code: 13435, error_labels: [], host: nil, message: "not master and slaveOk=false", resumable: true, retryable_reads: true, retryable_writes: true } } ``` -------------------------------- ### Add Mongo.Repo to Supervision Tree Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Illustrates how to include your custom `MyApp.Repo` module in the application's list of children for the supervision tree, ensuring it starts and runs. ```elixir children = [ # ... MyApp.Repo, # ... ] ``` -------------------------------- ### IEx Session for Change Stream Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/examples/change_stream/README.md An interactive Elixir shell (iex) session demonstrating connecting to a change stream, receiving tokens, inserting a document, and observing the resulting change event. ```elixir iex(2)> 16:10:05.018 [info] Connecting change stream 16:10:05.022 [info] Receiving new token nil iex(3)> Mongo.insert_one(:mongo, "http_errors", %{url: "https://elixir-lang.org"}) {:ok, %Mongo.InsertOneResult{ acknowledged: true, inserted_id: #BSON.ObjectId<5d595c42306a5f0d87ab24e7> }} iex(4)> 16:10:10.509 [info] Receiving new token %{"_data" => #BSON.Binary<825d595c420000000146645f696400645d595c42306a5f0d87ab24e7005a1004fefbdf8754024c339cd73f510a91db2b04>} 16:10:10.509 [info] Receiving new document %{"coll" => "http_errors", "db" => "db-1"} 16:10:10.509 [info] Got http error for url https://elixir-lang.org ``` -------------------------------- ### Enable SSL on MongoDB Server Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Provides instructions on how to enable SSL for a MongoDB server. This involves generating SSL certificates and keys, combining them, and starting the `mongod` process with SSL options. ```bash $ openssl req -newkey rsa:2048 -new -x509 -days 365 -nodes -out mongodb-cert.crt -keyout mongodb-cert.key $ cat mongodb-cert.key mongodb-cert.crt > mongodb.pem $ mongod --sslMode allowSSL --sslPEMKeyFile /path/to/mongodb.pem ``` -------------------------------- ### Application Release Migration Execution Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Elixir code for a release task to run database migrations when the application starts. This is useful for production environments where `mix` is not available. ```elixir defmodule MyApp.Release do @moduledoc """ Used for executing DB release tasks when run in production without mix installed. """ def migrate() do Application.load(:my_app) Application.ensure_all_started(:ssl) Application.ensure_all_started(:mongodb_driver) Mongo.start_link(name: :mongo_db, url: "mongodb://localhost:27017/my-database", timeout: 60_000, pool_size: 1, idle_interval: 10_000) Mongo.Migration.migrate() end end ``` -------------------------------- ### Observe Change Stream with GenServer Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/examples/change_stream/README.md Spawns a GenServer process to consume documents from a MongoDB change stream cursor. It iterates through documents and calls a handler function for each. ```elixir pid = spawn(fn -> Enum.each(get_cursor(state), fn doc -> new_doc(doc) end) end) ``` -------------------------------- ### Elixir MongoDB Index Creation and Dropping Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Provides examples for creating and dropping indexes on MongoDB collections using `Mongo.create_indexes/4` and `Mongo.drop_index/4`. Shows how to define index properties like keys, names, and uniqueness. ```elixir indexes = [[key: [files_id: 1, n: 1], name: "files_n_index", unique: true]] Mongo.create_indexes(top, "my_collection", indexes, opts) ``` ```elixir # Example for dropping an index (details not shown in source text, but implied by function name) # Mongo.drop_index(top, "my_collection", "index_name", opts) ``` -------------------------------- ### Use Pooled Connection in Application Supervisor Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Configures the MongoDB driver to start as a supervised process within an Elixir application, enabling robust connection pooling and management. ```elixir def start(_type, _args) do children = [ {Mongo, [name: :mongo_db, url: "mongodb://localhost:27017/test", pool_size: 3]} ] opts = [strategy: :one_for_one, name: MyApp.Supervisor] Supervisor.start_link(children, opts) end ``` -------------------------------- ### Elixir MongoDB Change Streams Monitoring Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Demonstrates using `Mongo.watch_collection` to monitor changes in MongoDB collections. Includes examples for direct processing and for sending change events to a monitor process. ```elixir seeds = ["hostname1.net:27017", "hostname2.net:27017", "hostname3.net:27017"] {:ok, top} = Mongo.start_link(database: "my-db", seeds: seeds, appname: "getting rich") stream = Mongo.watch_collection(top, "accounts", [], fn doc -> IO.puts "New Token #{inspect doc}" end, max_time: 2_000 ) Enum.each(stream, fn doc -> IO.puts inspect doc end) ``` ```elixir def for_ever(top, monitor) do stream = Mongo.watch_collection(top, "users", [], fn doc -> send(monitor, {:token, doc}) end) Enum.each(stream, fn doc -> send(monitor, {:change, doc}) end) end spawn(fn -> for_ever(top, self()) end) ``` -------------------------------- ### Control MongoDB Transactions Manually with Sessions Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Provides granular control over MongoDB transactions by manually managing sessions. It shows starting a session, starting/committing/ending a transaction, and associating sessions with insert operations. ```elixir alias Mongo.Session {:ok, session} = Session.start_session(top, :write, []) :ok = Session.start_transaction(session) Mongo.insert_one(top, "dogs", %{name: "Greta"}, session: session) Mongo.insert_one(top, "dogs", %{name: "Waldo"}, session: session) Mongo.insert_one(top, "dogs", %{name: "Tom"}, session: session) :ok = Session.commit_transaction(session) :ok = Session.end_session(top, session) ``` -------------------------------- ### Define Telemetry Metric for MongoDB Driver Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Provides an example of how to define a telemetry metric in a Phoenix application to track the execution duration of MongoDB driver commands, enabling monitoring in tools like the Phoenix Dashboard. ```elixir summary("mongodb_driver.execution.duration", tags: [:collection, :command], unit: {:microsecond, :millisecond} ) ``` -------------------------------- ### Configure MongoDB Connection in config.exs Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Shows how to set up the MongoDB connection details, including the database URL and various connection parameters like timeout and queue target, within the application's configuration file. ```config config :my_app, MyApp.Repo, url: "mongodb://localhost:27017/my-app-dev", timeout: 60_000, idle_interval: 10_000, queue_target: 5_000 ``` -------------------------------- ### Struct Creation and Conversion Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Demonstrates creating a new struct using the generated `new/0` function and performing map conversions using `dump/1` and `load/2`. ```Elixir iex(1)> x = Label.new() %Label{color: :red, name: "warning"} iex(2)> m = Label.dump(x) %{color: :red, name: "warning"} iex(3)> Label.load(m, true) %Label{color: :red, name: "warning"} ``` -------------------------------- ### Connect to MongoDB with Authentication Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Shows how to establish a connection to MongoDB with authentication credentials, specifying username, password, and the authentication source database. ```elixir # Starts an unpooled connection {:ok, top} = Mongo.start_link(url: "mongodb://localhost:27017/db-name", username: "test_user", password: "hunter2", auth_source: "admin_test") top |> Mongo.find("test-collection", %{}) |> Enum.to_list() ``` -------------------------------- ### Load Function Key Type Handling Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Explains and demonstrates how the `load/2` function handles different key types (binary vs. atom) when converting maps to structs, noting MongoDB's default binary keys. ```Elixir iex(1)> m = %{"color" => :red, "name" => "warning"} iex(2)> Label.load(m) %Label{color: :red, name: "warning"} iex(3)> Label.load(m, true) %Label{color: nil, name: nil} ``` -------------------------------- ### Run Migrations for Specific Topologies Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Illustrates how to execute database migrations for a specific topology by passing the topology name as an option to the `Mongo.Migration.migrate/1` function. This enables targeted migration runs. ```elixir IO.puts("running default migration") Mongo.Migration.migrate() ## default values specified in the configs IO.puts("running topology_2 migration") Mongo.Migration.migrate([topology: :topology_2]) ## override the topology ``` -------------------------------- ### Migration Script with Options Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Shows how to define `up/1` and `down/1` functions within a migration script to accept and utilize options passed during the migration process, allowing for dynamic migration logic. ```elixir defmodule Mongo.Migrations.Topology.CreateIndex do def up(opts) do IO.inspect(opts) # Migration logic here ... end def down(opts) do IO.inspect(opts) # Rollback logic here ... end end ``` -------------------------------- ### Generate Migration Script for a Topology Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Provides the command-line interface (CLI) syntax for generating a new migration script, specifying a topology name to organize it into a dedicated sub-folder and module namespace. ```shell mix mongo.gen.migration add_indexes topology_2 ``` -------------------------------- ### Migration Configuration Options Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Details the available configuration options for the migration module, including their purpose and default values. ```APIDOC Migration Configuration Options: * `:collection` - The name of the collection where migration versions are stored. Defaults to `"migrations"`. * `:path` - The directory path for migration scripts within the `priv` directory. Defaults to `"migrations"`. The full path is constructed as `:priv/:topology/:path`. * `:otp_app` - The name of the OTP application used to resolve the `priv` folder. Defaults to `:mongodb_driver`. Typically, this should be your application's name. * `:topology` - The topology used for running migrations. Defaults to `:mongo`. ``` -------------------------------- ### Elixir Migration Script Structure for Topology Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Demonstrates the expected structure of an Elixir migration script generated for a specific topology, including the module naming convention that reflects the topology. ```elixir defmodule Mongo.Migrations.Topology2.AddIndexes do # Migration implementation ... end ``` -------------------------------- ### Configure Mongo.Repo Module in Elixir Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Demonstrates how to use the `Mongo.Repo` macro to define a repository module for your Elixir application, specifying the OTP app and topology. ```elixir defmodule MyApp.Repo do use Mongo.Repo, otp_app: :my_app, topology: :mongo end ``` -------------------------------- ### Activate Zlib Compression Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Enables zlib compression for MongoDB driver connections by appending `compressors=zlib` to the connection URL. This requires no additional dependencies. ```elixir {:ok, top} = Mongo.start_link(url: "mongodb://localhost:27017/db?compressors=zlib") ``` -------------------------------- ### Run Migrations with Mix Task Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Command to execute pending database migrations using the mix task. This applies the `up` function of all unapplied migrations. ```shell mix mongo.migrate ``` -------------------------------- ### Migration Configuration Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Configuration options for the MongoDB driver's migration module. Specifies the topology, collection name, migration path, and OTP app. ```elixir config :mongodb_driver, migration: [ topology: :mongo, collection: "migrations", path: "migrations", otp_app: :mongodb_driver ] ``` -------------------------------- ### Elixir MongoDB Connection and Query Timeout Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Demonstrates setting the global connection timeout for `Mongo.start_link` and overriding it for individual queries using `Mongo.find`. Shows setting timeout values in milliseconds. ```elixir # Starts a pooled connection with a 60-second timeout {:ok, top} = Mongo.start_link(url: "mongodb://localhost:27017/db-name", timeout: 60_000) ``` ```elixir # Overrides the default timeout for a single query to 120 seconds Mongo.find(top, "dogs", %{}, timeout: 120_000) ``` -------------------------------- ### Connect to Replica Set using URI Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Connects to a MongoDB replica set using a connection string URI. The URI can list multiple hostnames to ensure robust discovery. ```elixir {:ok, pid} = Mongo.start_link(url: "mongodb://hostname1.net:27017/test") ``` ```elixir {:ok, pid} = Mongo.start_link(url: "mongodb://hostname1.net:27017,hostname2.net:27017,hostname3.net:27017/test") ``` -------------------------------- ### Manual Struct Conversion (Find One) Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Demonstrates manual conversion of a MongoDB map document to an Elixir struct after fetching it using `Mongo.find_one`. ```Elixir defmodule Label do defstruct name: "warning", color: "red" end iex> label_map = Mongo.find_one(:mongo, "labels", %{}) %{"name" => "warning", "color" => "red"} iex> label = %Label{name: label_map["name"], color: label_map["color"]} ``` -------------------------------- ### Using Mongo.Collection Macro Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Defines an Elixir struct `Label` using the `Mongo.Collection` macro to automate document handling, including attributes and default values. ```Elixir defmodule Label do use Mongo.Collection document do attribute :name, String.t(), default: "warning" attribute :color, String.t(), default: :red end end ``` -------------------------------- ### Generate Migration Script Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Command to generate a new Elixir migration script using the mix task. This creates a template file in the migrations directory. ```shell mix mongo.gen.migration add_indexes ``` -------------------------------- ### Elixir GridFS File Download Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Shows how to download a file previously stored in MongoDB GridFS. It requires a `Mongo.GridFs.Bucket` and the `file_id` of the target file. The download stream is opened, and its content is piped to a local file. ```elixir dest_filename = "/tmp/my-test-file.jps" with {:ok, stream} <- Mongo.GridFs.Download.open_download_stream(bucket, file_id) do stream |> Stream.into(File.stream!(dest_filename)) |> Stream.run end ``` -------------------------------- ### Activate Zstd Compression Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Enables zstd compression by adding the `ezstd` dependency to `mix.exs` and appending `compressors=zstd` to the connection URL. Zstd offers a good balance between compression rate and speed. ```elixir # Add to mix.exs dependencies: # {:ezstd, "~> 1.1"} {:ok, top} = Mongo.start_link(url: "mongodb://localhost:27017/db?compressors=zstd") ``` -------------------------------- ### MongoDB Authentication Mechanisms Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Summarizes the supported and unsupported authentication mechanisms for MongoDB connections. It highlights SCRAM as the default for v3.0+, PLAIN for LDAP, and notes the lack of GSSAPI (Kerberos) support. ```APIDOC Auth Mechanisms: - SCRAM: Default for MongoDB 3.0+. - PLAIN: Supported for LDAP authentication (MongoDB Enterprise Edition or Atlas). - GSSAPI: Not currently supported (used for Kerberos authentication). - MONGODB-X509: Supported for certificate-based authentication. Connection Options for X.509: - `auth_mechanism`: Set to `:x509`. - `username`: The username extracted from the certificate subject (e.g., "CN=cert-user"). - `password`: Must be an empty string for X.509 authentication. - `ssl`: Set to `true`. - `ssl_opts`: - `verify`: Typically `:verify_peer`. - `cacertfile`: Path to the CA certificate store (e.g., from `castore` package). - `certfile`: Path to the client's X.509 certificate file. - `customize_hostname_check`: Optional, for custom hostname verification (e.g., wildcard certificates). ``` -------------------------------- ### X.509 Authentication Configuration Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Details the configuration options required for establishing a MongoDB connection using X.509 client certificate authentication. This includes setting SSL options, specifying certificate paths, and defining the username from the certificate subject. ```elixir opts = [ url: "mongodb+srv://cluster0.xxx.mongodb.net/myFirstDatabase?authSource=%24external&retryWrites=true&w=majority", ssl: true, username: "CN=cert-user", password: "", auth_mechanism: :x509, ssl_opts: [ verify: :verify_peer, cacertfile: to_charlist(CAStore.file_path()), certfile: '/path-to-cert/X509-cert-2227052404946303101.pem', customize_hostname_check: [ match_fun: :public_key.pkix_verify_hostname_match_fun(:https) ] ]] Mongo.start_link(opts) ``` -------------------------------- ### Manual Struct Conversion (Insert One) Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Shows the reverse process of converting an Elixir struct into a map for insertion into MongoDB using `Mongo.insert_one`. ```Elixir iex> label = %Label{} iex> label_map = %{"name" => label.name, "color" => label.color} iex> {:ok, _} = Mongo.insert_one(:mongo, "labels", label_map) ``` -------------------------------- ### Software Lock Mechanism Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Elixir code demonstrating how to implement a software lock for the migration collection, as MongoDB does not support native collection locks. ```elixir Mongo.update_one(topology, "migrations", %{_id: "lock", used: false}, %{"\$set": %{used: true}}, upsert: true) ``` -------------------------------- ### Mongo Driver Functions Supporting Compression Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Lists the MongoDB driver functions that utilize network compression by default. Compression can be disabled per-call using `compression: false`. ```APIDOC Mongo Functions with Compression Support: - Mongo.aggregate/4 - Mongo.find/4 - Mongo.insert_one/4 - Mongo.insert_many/4 - Mongo.update/4 - Mongo.update_documents/6 - Mongo.find_one_and_update/5 - Mongo.find_one_and_replace/5 - Mongo.find_one_and_delete/4 - Mongo.count/4 - Mongo.distinct/5 - Mongo.delete_documents/5 - Mongo.create/4 Usage Example (disabling compression): Mongo.find(pid, collection, query, options \\ [compression: false]) ``` -------------------------------- ### Elixir GridFS File Upload Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Demonstrates uploading a file from the local filesystem to MongoDB using GridFS. It involves creating a `Mongo.GridFs.Bucket`, opening an upload stream, and piping the file content into the stream. The `upload_stream.id` can be used later to retrieve the file. ```elixir bucket = Bucket.new(top) upload_stream = Upload.open_upload_stream(bucket, "test.jpg") src_filename = "./test/data/test.jpg" File.stream!(src_filename, [], 512) |> Stream.into(upload_stream) |> Stream.run() file_id = upload_stream.id ``` -------------------------------- ### Connect to Replica Set using Seeds Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Connects to a MongoDB replica set by providing a list of seed hostnames. The driver automatically discovers the topology from these seeds. ```elixir {:ok, pid} = Mongo.start_link(database: "test", seeds: ["hostname1.net:27017"]) ``` ```elixir {:ok, pid} = Mongo.start_link(database: "test", seeds: ["hostname1.net:27017", "hostname2.net:27017", "hostname3.net:27017"]) ``` -------------------------------- ### Generated Module Structure Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Shows the typical structure of a module generated by `Mongo.Collection`, including `defstruct`, type specifications, and collection-related functions. ```Elixir defmodule Label do defstruct [name: "warning", color: "red"] @type t() :: %Label{String.t(), String.t()} def new()... def load(map)... def dump(%Label{})... def __collection__(:attributes)... def __collection__(:types)... def __collection__(:collection)... def __collection__(:id)... end ``` -------------------------------- ### MongoDB Driver Telemetry Event Execution Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Shows the Elixir code snippet demonstrating how the MongoDB driver emits telemetry events for command execution duration, including the metadata passed with the event. ```elixir metadata = %{ type: :mongodb_driver, command: command, params: parameters, collection: collection, options: Keyword.get(opts, :telemetry_options, []) } :telemetry.execute([:mongodb_driver, :execution], %{duration: duration}, metadata) ``` -------------------------------- ### Configure MongoDB Driver Logging Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Details how to enable and configure logging for the MongoDB driver by setting the `log` attribute in the application's configuration. This allows visibility into commands, collections, and parameters. ```config config :mongodb_driver, log: true ``` -------------------------------- ### Elixir MongoDB GridFS API Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Details the Elixir MongoDB driver's GridFS API for managing files. This includes creating file buckets, opening streams for uploading and downloading files, and handling file metadata. It provides the necessary functions to interact with MongoDB's GridFS specification. ```APIDOC Mongo.GridFs.Bucket: new(connection, opts \\ []) :: %Bucket{} - Creates a new GridFS bucket with default or specified options. - Parameters: - connection: The MongoDB connection identifier. - opts: Optional configuration for the bucket (e.g., bucket name). - Returns: A %Bucket{} struct. Mongo.GridFs.Upload: open_upload_stream(bucket, filename, opts \\ []) :: %UploadStream{} - Opens a stream to upload a file to the specified bucket. - Parameters: - bucket: The %Bucket{} struct. - filename: The name of the file to upload. - opts: Optional parameters for the upload (e.g., metadata, chunk size). - Returns: An %UploadStream{} struct containing the file ID and stream handle. write(upload_stream, data) :: :ok | {:error, any} - Writes data to the upload stream. close(upload_stream) :: :ok | {:error, any} - Closes the upload stream and finalizes the file upload. Mongo.GridFs.Download: open_download_stream(bucket, file_id, opts \\ []) :: {:ok, DownloadStream.t()} | {:error, any} - Opens a stream to download a file from the specified bucket using its ID. - Parameters: - bucket: The %Bucket{} struct. - file_id: The ID of the file to download. - opts: Optional parameters for the download. - Returns: A tuple containing {:ok, stream} or an error. read(download_stream) :: {:ok, binary} | :eof | {:error, any} - Reads data from the download stream. Related Modules: - Mongo.GridFs.Bucket - Mongo.GridFs.Download - Mongo.GridFs.Upload ``` -------------------------------- ### Perform MongoDB Transaction with Mongo.transaction/3 Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Demonstrates a basic MongoDB transaction using the `Mongo.transaction/3` function in Elixir. It shows how to insert multiple documents within a single transaction and return their IDs. ```elixir {:ok, ids} = Mongo.transaction(top, fn -> {:ok, %InsertOneResult{:inserted_id => id1}} = Mongo.insert_one(top, "dogs", %{name: "Greta"}) {:ok, %InsertOneResult{:inserted_id => id2}} = Mongo.insert_one(top, "dogs", %{name: "Waldo"}) {:ok, %InsertOneResult{:inserted_id => id3}} = Mongo.insert_one(top, "dogs", %{name: "Tom"}) {:ok, [id1, id2, id3]} end, w: 1) ``` -------------------------------- ### Elixir Streaming Unordered Bulk Writes Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Illustrates importing a large volume of data (1,000,000 integers) into MongoDB efficiently using streaming unordered bulk writes. This method reduces memory usage by accumulating operations in batches before sending them to the database. It leverages `Stream.map` and `Mongo.UnorderedBulk.write`. ```elixir 1..1_000_000 |> Stream.map(fn i -> Mongo.BulkOps.get_insert_one(%{number: i}) end) |> Mongo.UnorderedBulk.write(:mongo, "bulk", 1_000) |> Stream.run() ``` -------------------------------- ### Removing Struct Key Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Illustrates how to remove the `__struct__` key from a struct map before sending it to MongoDB, which the driver can then automatically convert. ```Elixir iex> Map.drop(label, [:__struct__]) %{color: :red, name: "warning"} ``` -------------------------------- ### Elixir Ordered Bulk Writes Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Demonstrates performing a sequence of ordered write operations (inserts, updates, deletes) to MongoDB. This ensures operations are executed in the specified order, which is crucial for maintaining data integrity in certain workflows. It uses the OrderedBulk module for building the operations. ```elixir bulk = "bulk" |> OrderedBulk.new() |> OrderedBulk.insert_one(%{name: "Greta"}) |> OrderedBulk.insert_one(%{name: "Tom"}) |> OrderedBulk.insert_one(%{name: "Waldo"}) |> OrderedBulk.update_one(%{name: "Greta"}, %{"$set": %{kind: "dog"}}) |> OrderedBulk.update_one(%{name: "Tom"}, %{"$set": %{kind: "dog"}}) |> OrderedBulk.update_one(%{name: "Waldo"}, %{"$set": %{kind: "dog"}}) |> OrderedBulk.update_many(%{kind: "dog"}, %{"$set": %{kind: "cat"}}) |> OrderedBulk.delete_one(%{kind: "cat"}) |> OrderedBulk.delete_one(%{kind: "cat"}) |> OrderedBulk.delete_one(%{kind: "cat"}) result = Mongo.BulkWrite.write(top, bulk, w: 1) ``` -------------------------------- ### Elixir MongoDB Bulk Write API Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Provides an overview of the Elixir MongoDB driver's bulk write capabilities. This includes modules for managing ordered and unordered operations, creating individual operations, and executing bulk writes. It covers the core functions for batching database modifications. ```APIDOC Mongo.BulkWrite: write(connection, bulk_operations, opts \\ []) - Executes a set of bulk write operations. - Parameters: - connection: The MongoDB connection identifier. - bulk_operations: A struct representing the bulk operations (e.g., from OrderedBulk or UnorderedBulk). - opts: Optional parameters, e.g., `w: 1` for write concern. - Returns: The result of the bulk write operation. Mongo.OrderedBulk: new() :: %OrderedBulk{} - Creates a new, empty ordered bulk operations struct. insert_one(bulk, document) :: %OrderedBulk{} - Adds an insert operation for a single document. update_one(bulk, filter, update, opts \\ []) :: %OrderedBulk{} - Adds an update operation for a single document matching the filter. update_many(bulk, filter, update, opts \\ []) :: %OrderedBulk{} - Adds an update operation for all documents matching the filter. delete_one(bulk, filter, opts \\ []) :: %OrderedBulk{} - Adds a delete operation for a single document matching the filter. delete_many(bulk, filter, opts \\ []) :: %OrderedBulk{} - Adds a delete operation for all documents matching the filter. Mongo.UnorderedBulk: write(connection, bulk_ops_or_stream, batch_size, opts \\ []) :: :ok | {:error, any} - Executes unordered bulk write operations, potentially from a stream. - Parameters: - connection: The MongoDB connection identifier. - bulk_ops_or_stream: Either a struct representing bulk operations or a stream of operations. - batch_size: The number of operations to group in each batch. - opts: Optional parameters. - Returns: Status of the write operation. Mongo.BulkOps: get_insert_one(document) :: %{op: :insert_one, document: map} - Creates a single insert operation document. get_update_one(filter, update, opts \\ []) :: %{op: :update_one, filter: map, update: map, opts: map} - Creates a single update operation document. get_delete_one(filter, opts \\ []) :: %{op: :delete_one, filter: map, opts: map} - Creates a single delete operation document. Related Modules: - Mongo.UnorderedBulk - Mongo.OrderedBulk - Mongo.BulkWrite - Mongo.BulkOps ``` -------------------------------- ### Elixir MongoDB Read Preferences Configuration Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Configures read preferences for MongoDB queries, specifying the mode, maximum staleness in milliseconds, and custom tags for server selection. Used with functions like `Mongo.find_one`. ```elixir prefs = %{ mode: :secondary, max_staleness_ms: 120_000, tags: [dc: "west", usage: "production"] } Mongo.find_one(top, "dogs", %{name: "Oskar"}, read_preference: prefs) ``` -------------------------------- ### Correctly Query with Attribute Mapping in Mongo.Repo Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Explains how to correctly query documents using `Mongo.Repo.get_by/2` when attribute names differ from their database mappings (e.g., `uuid` vs `u`). This is crucial for handling nested documents and ensuring queries work as expected. ```elixir defmodule MyApp.Session do @moduledoc false use Mongo.Collection alias BSON.Binary collection :s do attribute :uuid, Binary.t(), name: :u end end # Incorrect query (prior to understanding mapping) # MyApp.Repo.get_by(MyApp.Session, %{uuid: session_uuid}) # Correct query using mapped attribute name MyApp.Repo.get_by(MyApp.Session, %{u: session_uuid}) ``` -------------------------------- ### Transform Map with Key Order to List of Tuples Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Provides a utility module `MapWithOrder` to recursively transform BSON documents (represented as maps with an order key) into lists of tuples, preserving the original key order for potential re-encoding. ```elixir defmodule MapWithOrder do def to_list(doc, order_key \ :__order__) do do_to_list(doc, order_key) end defp do_to_list(%{__struct__: _} = elem, _order_key) do elem end defp do_to_list(doc, order_key) when is_map(doc) do doc |> Map.get(order_key, Map.keys(doc)) |> Enum.map(fn key -> {key, do_to_list(Map.get(doc, key), order_key)} end) end defp do_to_list(xs, order_key) when is_list(xs) do Enum.map(xs, fn elem -> do_to_list(elem, order_key) end) end defp do_to_list(elem, _order_key) do elem end end # Example usage: # doc = ... # MapWithOrder.to_list(doc) ``` -------------------------------- ### Process Mongo.Stream with Enum Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Demonstrates the recommended way to process a `Mongo.Stream` using `Enum.to_list()` to ensure proper session management. Avoid direct access to internal `Mongo.Stream` fields as it can lead to unclosed sessions. ```elixir @topology |> Mongo.aggregate(collection, pipeline, opts) |> Enum.to_list() ``` -------------------------------- ### MongoDB Find Operations with Query Operators Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Illustrates how to use various MongoDB query operators such as `$and`, `$or`, and `$in` within the `Mongo.find` function to construct complex queries. ```elixir @topology |> Mongo.find("users", %{"and" => [%{email: "my@email.com"}, %{first_name: "first_name"}]}) |> Enum.to_list() ``` ```elixir @topology |> Mongo.find("users", %{"or" => [%{email: "my@email.com"}, %{first_name: "first_name"}]}) |> Enum.to_list() ``` ```elixir @topology |> Mongo.find("users", %{email: %{"in" => ["my@email.com", "other@email.com"]}}) |> Enum.to_list() ``` -------------------------------- ### Measure Query Performance with Batch Size Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Measures the execution time of a `Mongo.find` query using `:timer.tc/1`, demonstrating how to tune `batch_size` for potential performance improvements. ```elixir :timer.tc(fn -> Mongo.find(top, "tasks", %{}, limit: 30_000, batch_size: 1000) |> Stream.reject(fn _x -> true end) |> Stream.run() end) ``` -------------------------------- ### Implement Nested MongoDB Transactions in Elixir Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Illustrates how to use nested transactions in Elixir with the MongoDB driver. It defines helper functions for inserting dogs and shows how they can be called within a transaction, including calling another transaction function. ```elixir def insert_dog(top, name) do Mongo.insert_one(top, "dogs", %{name: name}) end def insert_dogs(top) do Mongo.transaction(top, fn -> insert_dog(top, "Tom") insert_dog(top, "Bell") insert_dog(top, "Fass") :ok end) end :ok = Mongo.transaction(top, fn -> insert_dog(top, "Greta") insert_dogs(top) end) ``` -------------------------------- ### Disable Compression for a Single Function Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Demonstrates how to disable network compression for a specific MongoDB driver function call by passing the `compression: false` option. ```elixir Mongo.find(top, "tasks", %{}, compression: false) |> Enum.to_list() ``` -------------------------------- ### Implement Custom Struct Encoding for MongoDB Source: https://github.com/zookzook/elixir-mongodb-driver/blob/master/README.md Demonstrates how to implement the `Mongo.Encoder` protocol for a custom Elixir struct. This allows the struct to be automatically converted into a map format suitable for insertion into a MongoDB collection. ```elixir defmodule CustomStruct do @fields [:a, :b, :c, :id] @enforce_keys @fields defstruct @fields defimpl Mongo.Encoder do def encode(%{a: a, b: b, id: id}) do %{ _id: id, a: a, b: b, custom_encoded: true } end end end # Example struct: # %CustomStruct{a: 10, b: 20, c: 30, id: "5ef27e73d2a57d358f812001"} # This struct will be written to MongoDB as: # { # "a": 10, # "b": 20, # "custom_encoded": true, # "_id": "5ef27e73d2a57d358f812001" # } ```