{"id":13480692,"url":"https://github.com/comtihon/mongodb-erlang","last_synced_at":"2025-04-13T07:50:36.588Z","repository":{"id":2094436,"uuid":"3034911","full_name":"comtihon/mongodb-erlang","owner":"comtihon","description":"MongoDB driver for Erlang","archived":false,"fork":false,"pushed_at":"2024-04-02T21:04:09.000Z","size":2518,"stargazers_count":343,"open_issues_count":62,"forks_count":268,"subscribers_count":55,"default_branch":"master","last_synced_at":"2025-04-04T05:08:07.035Z","etag":null,"topics":["erlang","mongodb"],"latest_commit_sha":null,"homepage":"","language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/comtihon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2011-12-22T16:11:02.000Z","updated_at":"2025-02-26T10:34:30.000Z","dependencies_parsed_at":"2024-01-05T23:56:58.659Z","dependency_job_id":"aaf744f4-36b9-40a8-91ff-4aa36bb59e79","html_url":"https://github.com/comtihon/mongodb-erlang","commit_stats":{"total_commits":440,"total_committers":49,"mean_commits":8.979591836734693,"dds":0.5454545454545454,"last_synced_commit":"5881a8b689156feb9931fd47ee864c8c2491b03a"},"previous_names":[],"tags_count":67,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/comtihon%2Fmongodb-erlang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/comtihon%2Fmongodb-erlang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/comtihon%2Fmongodb-erlang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/comtihon%2Fmongodb-erlang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/comtihon","download_url":"https://codeload.github.com/comtihon/mongodb-erlang/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248681494,"owners_count":21144700,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["erlang","mongodb"],"created_at":"2024-07-31T17:00:43.727Z","updated_at":"2025-04-13T07:50:36.563Z","avatar_url":"https://github.com/comtihon.png","language":"Erlang","funding_links":[],"categories":["Erlang","Libraries"],"sub_categories":["Erlang"],"readme":"This is the [MongoDB](https://www.mongodb.org/) driver for Erlang.\n\n[![Run tests](https://github.com/comtihon/mongodb-erlang/actions/workflows/test.yml/badge.svg)](https://github.com/comtihon/mongodb-erlang/actions/workflows/test.yml)\n[![Enot](https://enot.justtech.blog/badge?full_name=comtihon/mongodb-erlang)](https://enot.justtech.blog)\n\n### Usage\nAdd this repo as the dependency:\nRebar\n\n    {deps, [\n      {mongodb, \".*\",\n       {git, \"git://github.com/comtihon/mongodb-erlang\", {tag, \"\u003cLatest tag\u003e\"}}}\n       ]\n    }\nErlang.mk\n\n    DEPS = mongodb\n    dep_mongodb = git https://github.com/comtihon/mongodb-erlang.git \u003cLatest tag\u003e\nWhere __Latest tag__ is the latest tag from github.\n\n### Installing\nIf you want to use it from command line - download and compile the application:\n\n\t$ git clone git://github.com/comtihon/mongodb-erlang.git mongodb\n\t$ cd mongodb\n\t$ make\nYou will need `erlang` 18+ and `make` installed.\n\n### Starting and using the api\nStart all applications, needed by mongodb\n\n\t\u003e application:ensure_all_started (mongodb).\n\n__Important__:\n`mongoc` API was changed in `3.0.0`.\n`mc_cursor` API was changed in `3.0.0.`\n\nThis driver has two api modules - `mc_worker_api` and `mongo_api`.\n`mc_worker_api` works directly with one connection, while all `mongo_api`\ninterfaces refer to `mongoc` pool. Although `mongoc` is not stable for now\nyou should use it if you have shard and need to determine mongo topology.\nIf you are choosing between using\n[mongos](https://docs.mongodb.com/manual/reference/program/mongos/) and\nusing mongo shard with `mongo_api` - prefer mongos and use `mc_worker_api`.\n\nmc_worker_api -- direct connection client\n---------------------------------\n\n### Connecting\nTo connect to a database `test` on mongodb server listening on\n`localhost:27017` (or any address \u0026 port of your choosing)\nuse `mc_worker_api:connect/1`.\n\n\t\u003e Database = \u003c\u003c\"test\"\u003e\u003e.\n\t\u003e {ok, Connection} = mc_worker_api:connect ([{database, Database}]).\n\n`mc_worker_api:connect` returns `{error, Reason}` if it failed to connect.\n See arguments you can pass in `mc_worker_api.erl` type spec:\n\n    -type arg() :: {database, database()}\n    | {login, binary()}\n    | {password, binary()}\n    | {w_mode, write_mode()}\n    | {r_mode, read_mode()}\n    | {host, list()}\n    | {port, integer()}\n    | {register, atom() | fun()}\n    | {next_req_fun, fun()}.\nTo connect mc_worker in your supervised pool, use `mc_worker:start_link/1`\ninstead and pass all args to it.\n\n`safe`, along with `{safe, GetLastErrorParams}` and `unsafe`, are\nwrite-modes. Safe mode makes a *getLastError* request\nafter every write in the sequence. If the reply says it failed then\nthe rest of the sequence is aborted and returns\n`{failure, {write_failure, Reason}}`, or `{failure, not_master}` when\nconnected to a slave. An example write\nfailure is attempting to insert a duplicate key that is indexed to be\nunique. Alternatively, unsafe mode issues every\nwrite without a confirmation, so if a write fails you won't know about\nit and remaining operations will be executed.\nThis is unsafe but faster because you there is no round-trip delay.\n\n`master`, along with `slave_ok`, are read-modes. `master` means every\nquery in the sequence must read fresh data (from\na master/primary server). If the connected server is not a master then\nthe first read will fail, the remaining operations\nwill be aborted, and `mongo:do` will return `{failure, not_master}`.\n`slave_ok` means every query is allowed to read\nstale data from a slave/secondary (fresh data from a master is fine too).\n\nRead-modes only apply to the deprecated mc_worker_api query commands. Pass\na `readopts` map, like `#{\u003c\u003c\"mode\"\u003e\u003e =\u003e \u003c\u003c\"primary\"\u003e\u003e}` to an `mc_worker_api`\nfunction like\n`find_one(Conn, Coll, Selector, [{readopts, #{\u003c\u003c\"mode\"\u003e\u003e =\u003e \u003c\u003c\"primary\"\u003e\u003e}}])`\nfor the new API.\n\nIf you set `{register, Name}` option - mc_worker process will be\nregistered on this Name, or you can pass function\n`fun(pid())`, which it runs with self pid.\nIf you set `{login, Login}` and `{password, Password}` options -\nmc_worker will try to authenticate to the database.\n\n`next_req_fun` is a function caller every time, when worker sends\nrequest to database. It can be use to optimise pool\nusage. When you use poolboy transaction (or mongoc transaction, which\nuse poolboy transaction) - `mc_worker` sends request\nto database and do nothing, waiting for reply. You can use\n`{next_req_fun, fun() -\u003e poolboy:checkin(?DBPOOL, self()) end}`\nto make workers return to pool as soon as they finish request.\nWhen response from database comes back - it will be saved in\nmc_worker msgbox. Msgbox will be processed just before the next\ncall to mc_worker.\n__Notice__, that poolboy's pool should be created with `{strategy, fifo}`\nto make uniform usage of pool workers.\n\n### Writing\nAfter you connected to your database - you can carry out write operations,\nsuch as `insert`, `update` and `delete`:\n\n    \u003e Collection = \u003c\u003c\"test\"\u003e\u003e.\n    \u003e mc_worker_api:insert(Connection, Collection, [\n                                                       #{\u003c\u003c\"name\"\u003e\u003e =\u003e \u003c\u003c\"Yankees\"\u003e\u003e,\n                                                         \u003c\u003c\"home\"\u003e\u003e =\u003e #{\u003c\u003c\"city\"\u003e\u003e =\u003e \u003c\u003c\"New York\"\u003e\u003e, \u003c\u003c\"state\"\u003e\u003e =\u003e \u003c\u003c\"NY\"\u003e\u003e},\n                                                         \u003c\u003c\"league\"\u003e\u003e =\u003e \u003c\u003c\"American\"\u003e\u003e},\n                                                       #{\u003c\u003c\"name\"\u003e\u003e =\u003e \u003c\u003c\"Mets\"\u003e\u003e,\n                                                         \u003c\u003c\"home\"\u003e\u003e =\u003e #{\u003c\u003c\"city\"\u003e\u003e =\u003e \u003c\u003c\"New York\"\u003e\u003e, \u003c\u003c\"state\"\u003e\u003e =\u003e \u003c\u003c\"NY\"\u003e\u003e},\n                                                         \u003c\u003c\"league\"\u003e\u003e =\u003e \u003c\u003c\"National\"\u003e\u003e},\n                                                       #{\u003c\u003c\"name\"\u003e\u003e =\u003e \u003c\u003c\"Phillies\"\u003e\u003e,\n                                                         \u003c\u003c\"home\"\u003e\u003e =\u003e #{\u003c\u003c\"city\"\u003e\u003e =\u003e \u003c\u003c\"Philadelphia\"\u003e\u003e, \u003c\u003c\"state\"\u003e\u003e =\u003e \u003c\u003c\"PA\"\u003e\u003e},\n                                                         \u003c\u003c\"league\"\u003e\u003e =\u003e \u003c\u003c\"National\"\u003e\u003e},\n                                                       #{\u003c\u003c\"name\"\u003e\u003e =\u003e \u003c\u003c\"Red Sox\"\u003e\u003e,\n                                                         \u003c\u003c\"home\"\u003e\u003e=\u003e #{\u003c\u003c\"city\"\u003e\u003e =\u003e \u003c\u003c\"Boston\"\u003e\u003e, \u003c\u003c\"state\"\u003e\u003e =\u003e \u003c\u003c\"MA\"\u003e\u003e},\n                                                         \u003c\u003c\"league\"\u003e\u003e =\u003e \u003c\u003c\"American\"\u003e\u003e}\n                                                     ]),\nAn insert example (from `mongo_SUITE` test module). `Connection` is your\nConnection, got `from mc_worker_api:connect`, `Collection`\nis your collection name, `Doc` is something, you want to save.\nDoc will be returned, if insert succeeded. If Doc doesn't contains `_id`\n field - an updated Doc will be returned - with\nautomatically generated '_id' fields. If error occurred - Connection will\n fall.\n\n    \u003e mc_worker_api:delete(Connection, Collection, Selector).\nDelete example. `Connection` is your Connection, `Collection` - is a\ncollection you want to clean. `Selector` is the\nrules for cleaning. If you want to clean everything - pass empty `{}`.\nYou can also use maps instead bson documents:\n\n    \u003e Collection = \u003c\u003c\"test\"\u003e\u003e.\n    \u003e mc_worker_api:insert(Connection, Collection, #{\u003c\u003c\"name\"\u003e\u003e =\u003e \u003c\u003c\"Yankees\"\u003e\u003e, \u003c\u003c\"home\"\u003e\u003e =\u003e\n      #{\u003c\u003c\"city\"\u003e\u003e =\u003e \u003c\u003c\"New York\"\u003e\u003e, \u003c\u003c\"state\"\u003e\u003e =\u003e \u003c\u003c\"NY\"\u003e\u003e}, \u003c\u003c\"league\"\u003e\u003e =\u003e \u003c\u003c\"American\"\u003e\u003e}),\n\n### Reading\nTo call read operations use `find`, `find_one`:\n\n    \u003e {ok, Cursor} = mc_worker_api:find(Connection, Collection, Selector)\nAll params similar to `delete`.\nThe difference between `find` and `find_one` is in return. Find_one just\nreturns your result, while find returns you a\n`Cursor` - special process' pid. You can query data through the process\nwith the help of `mc_cursor' module.\n\n    \u003e Result = mc_cursor:next(Cursor),\n    \u003e mc_cursor:close(Cursor),\n__Important!__ Do not forget to close cursors after using them!\n`mc_cursor:rest` closes the cursor automatically.\n\nTo search for params - specify `Selector`:\n\n    mc_worker_api:find_one(Connection, Collection, #{\u003c\u003c\"key\"\u003e\u003e =\u003e \u003c\u003c\"123\"\u003e\u003e}).\nwill return one document from collection Collection with key == \u003c\u003c\"123\"\u003e\u003e.\n\n    mc_worker_api:find_one(Connection, Collection, #{\u003c\u003c\"key\"\u003e\u003e =\u003e \u003c\u003c\"123\"\u003e\u003e, \u003c\u003c\"value\"\u003e\u003e =\u003e \u003c\u003c\"built_in\"\u003e\u003e}).\nwill return one document from collection Collection with key == \u003c\u003c\"123\"\u003e\u003e\n`and` value == \u003c\u003c\"built_in\"\u003e\u003e.\nTuples `{\u003c\u003c\"key\"\u003e\u003e, \u003c\u003c\"123\"\u003e\u003e}` in first example and `{\u003c\u003c\"key\"\u003e\u003e, \u003c\u003c\"123\"\u003e\u003e,\n \u003c\u003c\"value\"\u003e\u003e, \u003c\u003c\"built_in\"\u003e\u003e}` are selectors.\n\nFor filtering result - use `Projector`:\n\n    mc_worker_api:find_one(Connection, Collection, {}, #{projector =\u003e #{\u003c\u003c\"value\"\u003e\u003e =\u003e true}).\nwill return one document from collection Collection with fetching `only`\n_id and value.\n\n    mc_worker_api:find_one(Connection, Collection, {}, #{projector =\u003e #{\u003c\u003c\"key\"\u003e\u003e =\u003e false, \u003c\u003c\"value\"\u003e\u003e =\u003e false}}).\nwill return your data without key and value params. If there is no other\ndata - only _id will be returned.\n\n### Updating\nTo add or update field in document - use `mc_worker_api:update` function\n with `$set` param.\nThis updates selected fields:\n\n    Command = #{\u003c\u003c\"$set\"\u003e\u003e =\u003e #{\n        \u003c\u003c\"quantity\"\u003e\u003e =\u003e 500,\n        \u003c\u003c\"details\"\u003e\u003e =\u003e #{\u003c\u003c\"model\"\u003e\u003e =\u003e \"14Q3\", \u003c\u003c\"make\"\u003e\u003e =\u003e \"xyz\"},\n        \u003c\u003c\"tags\"\u003e\u003e =\u003e [\"coats\", \"outerwear\", \"clothing\"]\n    }},\n    mc_worker_api:update(Connection, Collection, #{\u003c\u003c\"_id\"\u003e\u003e =\u003e 100}, Command),\nThis will add new field `expired`, if there is no such field, and set it\nto true.\n\n    Command = #{\u003c\u003c\"$set\"\u003e\u003e =\u003e #{\u003c\u003c\"expired\"\u003e\u003e =\u003e true}},\n    mc_worker_api:update(Connection, Collection, #{\u003c\u003c\"_id\"\u003e\u003e =\u003e 100}, Command),\nThis will update fields in nested documents.\n\n    Command = #{\u003c\u003c\"$set\"\u003e\u003e =\u003e #{\u003c\u003c\"details.make\"\u003e\u003e =\u003e \"zzz\"}},\n    mc_worker_api:update(Connection, Collection, #{\u003c\u003c\"_id\"\u003e\u003e =\u003e 100}, Command),\nThis will update elements in array.\n\n    Command = #{\u003c\u003c\"$set\"\u003e\u003e =\u003e #{\n        \u003c\u003c\"tags.1\"\u003e\u003e =\u003e \"rain gear\",\n        \u003c\u003c\"ratings.0.rating\"\u003e\u003e =\u003e 2\n      }},\n    mc_worker_api:update(Connection, Collection, #{'_id' =\u003e 100}, Command),\nFor result of executing this functions - see mongo_SUITE update test.\n\n### Creating indexes\nTo create indexes - use `mc_worker_api:ensure_index/3` command:\n\n    mc_worker_api:ensure_index(Connection, Collection, #{\u003c\u003c\"key\"\u003e\u003e =\u003e #{\u003c\u003c\"index\"\u003e\u003e =\u003e 1}}).  %simple\n    mc_worker_api:ensure_index(Connection, Collection, #{\u003c\u003c\"key\"\u003e\u003e =\u003e #{\u003c\u003c\"index\"\u003e\u003e =\u003e 1}, \u003c\u003c\"name\"\u003e\u003e =\u003e \u003c\u003c\"MyI\"\u003e\u003e}).  %advanced\n    mc_worker_api:ensure_index(Connection, Collection, #{\u003c\u003c\"key\"\u003e\u003e =\u003e #{\u003c\u003c\"index\"\u003e\u003e =\u003e 1}, \u003c\u003c\"name\"\u003e\u003e =\u003e \u003c\u003c\"MyI\"\u003e\u003e, \u003c\u003c\"unique\"\u003e\u003e =\u003e true, \u003c\u003c\"dropDups\"\u003e\u003e =\u003e true}).  %full\n\nensure_index takes `mc_worker`' pid or atom name as first parameter,\ncollection, where to create index, as second\nparameter and bson document with index\nspecification - as third parameter. In index specification one can set all\nor only some parameters.\nIf index specification is not full - it is automatically filled with\nvalues: `name, Name, unique, false, dropDups,\nfalse`, where `Name` is index's key.\n\n### Administering\nThis driver does not provide helper functions for commands. Use\n`mc_worker_api:command` directly and refer to the\n[MongoDB documentation](http://www.mongodb.org/display/DOCS/Commands)\nfor how to issue raw commands.\n\n### Authentication\nTo authenticate use function `mc_worker_api:connect`, or\n`mc_worker:start_link([...{login, \u003c\u003c\"login\"\u003e\u003e}, {password, \u003c\u003c\"password\"\u003e\u003e}...]`\n\n### Timeout\n\nBy default timeout for all connections to connection gen_server is `infinity`.\nIf you found problems with it - you can\nmodify timeout.\nTo modify it just add `mc_worker_call_timeout` with new value to your\n applications's env config.\n\nTimeout for operations with cursors may be explicitly passed to `mc_cursor:next/2`,\n `mc_cursor:take/3`, `mc_cursor:rest/2`, and `mc_cursor:foldl/5` functions,\n by default used value of `cursor_timeout` from application config, or `\n infinity` if `cursor_timeout` not specified.\n\n### Pooling\n\nIf you need simple pool - use modified [Poolboy](https://github.com/comtihon/poolboy),\nwhich is included in this app's deps. As a worker module use `mc_worker_api`.\nIf you need pool to mongo shard with determining topology - use `mongo_api`\nfor automatic topology discovery and monitoring. It uses poolboy inside.\n\n\nmongoc -- client with automatic MongoDB topology discovery and monitoring\n-------------------------------------------------------------------------\n\nYou can use `mongo_api.erl` for easy working with mongoc.\n\n### Connection\n\nFor opening a connection to a MongoDB server you can call `mongoc:connect/3`:\n\n```erlang\n{ok, Topology} = mongoc:connect(Seed, Options, WorkerOptions)\n```\n\nWhere `Seed` contains information about host names and ports to connect\n and info about topology of MongoDB deployment.\n\nSo you can pass just a hostname with port (or tuple with single key) for\nconnection to a single server deployment:\n\n```erlang\nSingleSeed = \"hostname:27017\",\nSingleSeedTuple = { single, \"hostname:27017\" }\n```\n\nIf you want to connect to a replica set _ReplicaSetName_ use this format\n of the `Seed` value:\n\n```erlang\nReplicaSeed = { rs, \u003c\u003c\"ReplicaSetName\"\u003e\u003e, [ \"hostname1:port1\", \"hostname2:port2\"] }\n```\n\nTo connect to a sharded cluster of mongos:\n\n```erlang\nShardedSeed = { sharded,  [\"hostname1:port1\", \"hostname2:port2\"] }\n```\n\nAnd if you want your MongoDB deployment metadata to be auto-discovered use\nthe `unknown` type in the `Seed` tuple:\n\n```erlang\nAutoDiscoveredSeed = { unknown,  [\"hostname1:port1\", \"hostname2:port2\"] }\n```\n\nmongoc topology **Options**\n\n```erlang\n[\n    { name,  Name },    % Name should be used for mongoc pool to be registered with\n    { register,  Name },    % Name should be used for mongoc topology process to be registered with\n\n    { pool_size, 5 }, % pool size on start\n    { max_overflow, 10 },\t% number of overflow workers be created, when all workers from pool are busy\n    { overflow_ttl, 1000 }, % number of milliseconds for overflow workers to stay in pool before terminating\n    { overflow_check_period, 1000 }, % overflow_ttl check period for workers (in milliseconds)\n\n    { localThresholdMS, 1000 }, % secondaries only which RTTs fit in window from lower RTT to lower RTT + localThresholdMS could be selected for handling user's requests\n\n    { connectTimeoutMS, 20000 },\n    { socketTimeoutMS, 100 },\n\n    { serverSelectionTimeoutMS, 30000 }, % max time appropriate server should be select by\n    { waitQueueTimeoutMS, 1000 }, % max time for waiting worker to be available in the pool\n\n    { heartbeatFrequencyMS, 10000 },    %  delay between Topology rescans\n    { minHeartbeatFrequencyMS, 1000 },\n\n    { rp_mode, primary }, % default ReadPreference mode - primary, secondary, primaryPreferred, secondaryPreferred, nearest\n\n    { rp_tags, [{tag,1}] }, % tags that servers shoul be tagged by for becoming candidates for server selection  (may be an empty list)\n]\n```\n\nmongoc **WorkerOptions** (as described in mongo Connecting chapter)\n\n```erlang\n-type arg() :: {database, database()}\n| {login, binary()}\n| {password, binary()}\n| {w_mode, write_mode()}.\n```\n\n\n### More Documentation\n\n[API Docs](http://api.mongodb.org/erlang/mongodb/) - Documentation generated from source code comments\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcomtihon%2Fmongodb-erlang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcomtihon%2Fmongodb-erlang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcomtihon%2Fmongodb-erlang/lists"}