{"id":17680714,"url":"https://github.com/elbywan/moongoon","last_synced_at":"2025-07-22T18:33:41.436Z","repository":{"id":54520085,"uuid":"257662925","full_name":"elbywan/moongoon","owner":"elbywan","description":"An object-document mapper for MongoDB.  🌙","archived":false,"fork":false,"pushed_at":"2024-10-11T19:37:58.000Z","size":346,"stargazers_count":45,"open_issues_count":1,"forks_count":3,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-04-08T16:11:21.091Z","etag":null,"topics":["crystal","mongo","mongodb","odm"],"latest_commit_sha":null,"homepage":"https://elbywan.github.io/moongoon/","language":"Crystal","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/elbywan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":"elbywan","custom":["https://www.paypal.me/elbywan"]}},"created_at":"2020-04-21T17:16:57.000Z","updated_at":"2025-03-16T06:58:22.000Z","dependencies_parsed_at":"2024-11-16T11:04:00.981Z","dependency_job_id":null,"html_url":"https://github.com/elbywan/moongoon","commit_stats":{"total_commits":106,"total_committers":2,"mean_commits":53.0,"dds":"0.16981132075471694","last_synced_commit":"e6cd65be3c869a8ea7b802f82d349b116d6e15b8"},"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"purl":"pkg:github/elbywan/moongoon","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elbywan%2Fmoongoon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elbywan%2Fmoongoon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elbywan%2Fmoongoon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elbywan%2Fmoongoon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/elbywan","download_url":"https://codeload.github.com/elbywan/moongoon/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elbywan%2Fmoongoon/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266552503,"owners_count":23947174,"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","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["crystal","mongo","mongodb","odm"],"created_at":"2024-10-24T09:08:41.319Z","updated_at":"2025-07-22T18:33:41.410Z","avatar_url":"https://github.com/elbywan.png","language":"Crystal","funding_links":["https://github.com/sponsors/elbywan","https://www.paypal.me/elbywan"],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\t\u003cimg src=\"icon.svg\" width=\"128\" height=\"128\" /\u003e\n\t\u003ch1\u003emoongoon\u003c/h1\u003e\n  \u003ch3\u003eA MongoDB ODM written in Crystal.\u003c/h3\u003e\n  \u003ca href=\"https://travis-ci.org/elbywan/moongoon\"\u003e\u003cimg alt=\"travis-badge\" src=\"https://travis-ci.org/elbywan/moongoon.svg?branch=master\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/elbywan/moongoon/tags\"\u003e\u003cimg alt=\"GitHub tag (latest SemVer)\" src=\"https://img.shields.io/github/v/tag/elbywan/moongoon\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/elbywan/moongoon/blob/master/LICENSE\"\u003e\u003cimg alt=\"GitHub\" src=\"https://img.shields.io/github/license/elbywan/moongoon\"\u003e\u003c/a\u003e\n\u003c/div\u003e\n\n\u003chr/\u003e\n\n#### An object-document mapper (ODM) library written in Crystal which makes interacting with MongoDB a breeze.\n\nThis library relies on:\n- [`cryomongo`](https://github.com/elbywan/cryomongo) as the underlying MongoDB driver.\n- [`bson.cr`](https://github.com/elbywan/bson.cr) as the BSON implementation.\n\n*For the moongoon version relying on the [`mongo.cr`](https://github.com/elbywan/mongo.cr) driver, please check the [mongo.cr](https://github.com/elbywan/moongoon/tree/mongo.cr) branch.*\n\n## Installation\n\n1. Add the dependency to your `shard.yml`:\n\n```yaml\ndependencies:\n  moongoon:\n    github: elbywan/moongoon\n```\n\n2. Run `shards install`\n\n3. Profit! 💰\n\n## Usage\n\n### Minimal working example\n\n```crystal\nrequire \"moongoon\"\n\n# A Model inherits from `Moongoon::Collection`\nclass User \u003c Moongoon::Collection\n  collection \"users\"\n\n  index keys: { name: 1, age: 1 }, options: { unique: true }\n\n  property name : String\n  property age : Int32\n  property pets : Array(Pet)\n\n  # Nested models inherit from `Moongoon::Document`\n  class Pet \u003c Moongoon::Document\n    property pet_name : String\n  end\nend\n\n# Connect to the mongodb instance.\nMoongoon.connect(\"mongodb://localhost:27017\", database_name: \"my_database\")\n\n# Initialize a model from arguments…\nuser = User.new(name: \"Eric\", age: 10, pets: [\n  User::Pet.new(pet_name: \"Mr. Kitty\"),\n  User::Pet.new(pet_name: \"Fluffy\")\n])\n# …or JSON data…\nuser = User.from_json(%(\n  \"name\": \"Eric\",\n  \"age\": 10,\n  \"pets\": [\n    { \"pet_name\": \"Mr. Kitty\" },\n    { \"pet_name\": \"Fluffy\" }\n  ]\n))\n# …or from querying the database.\nuser = User.find_one!({ name: \"Eric\" })\n\n# Insert a model in the database.\nuser.insert\n\n# Modify it.\nuser.name = \"Kyle\"\nuser.update\n\n# Delete it.\nuser.remove\n```\n\n### Connecting\n\n[**API documentation**](https://elbywan.github.io/moongoon/Moongoon/Database.html)\n\n- [Initial connection](https://elbywan.github.io/moongoon/Moongoon/Database.html#connect(database_url:String=\"mongodb://localhost:27017\",database_name:String=\"database\",*,reconnection_delay=5.seconds)-instance-method)\n- [Hooks](https://elbywan.github.io/moongoon/Moongoon/Database.html#after_connect(\u0026block:Proc(Nil))-instance-method)\n- [Low-level](https://elbywan.github.io/moongoon/Moongoon.html#client:Mongo::Client-class-method)\n\n```crystal\nrequire \"moongoon\"\n\nMoongoon.before_connect {\n  puts \"Connecting…\"\n}\nMoongoon.after_connect {\n  puts \"Connected!\"\n}\n\n# … #\n\nMoongoon.connect(\n  database_url: \"mongodb://address:27017\",\n  database_name: \"my_database\"\n)\n\n# In case you need to perform a low level query, use `Moongoon.client` or `Moongoon.database`.\n# Here, *db* is a `cryomongo` Mongo::Database. (For more details, check the `cryomongo` documentation)\ndb = Moongoon.database\ncursor = db[\"my_collection\"].list_indexes\nputs cursor.to_a.to_json\n```\n\n### Models\n\n[**API documentation**](https://elbywan.github.io/moongoon/Moongoon/Collection.html)\n\n- [Indexes](https://elbywan.github.io/moongoon/Moongoon/Collection.html#index(collection:String?=nil,database:String?=nil,options=NamedTuple.new,name:String?=nil,**keys):Nil-class-method)\n- [Relationships](https://elbywan.github.io/moongoon/Moongoon/Collection.html#reference(field,*,model,many=false,delete_cascade=false,clear_reference=false,back_reference=nil)-macro)\n- [Aggregations](https://elbywan.github.io/moongoon/Moongoon/Collection.html#aggregation_pipeline(*args)-class-method)\n- [Versioning](https://elbywan.github.io/moongoon/Moongoon/Collection/Versioning.html#versioning(ref_field=nil,auto=false,\u0026transform)-macro)\n\n```crystal\nrequire \"moongoon\"\n\nclass MyModel \u003c Moongoon::Collection\n  collection \"models\"\n\n  # Note: the database can be changed - if different from the default one\n  # database \"database_name\"\n\n  # Define indexes\n  index keys: { name: 1 }\n\n  # Specify agregation pipeline stages that will automatically be used for queries.\n  aggregation_pipeline(\n    {\n      \"$addFields\": {\n        count: {\n          \"$size\": \"$array\"\n        }\n      }\n    },\n    {\n      \"$project\": {\n        array: 0\n      }\n    }\n  )\n\n  # Collection fields\n  property name : String\n  property count : Int32?\n  property array : Array(Int32)? = [1, 2, 3]\nend\n\n# …assuming moongoon is connected… #\n\nMyModel.clear\n\nmodel = MyModel.new(\n  name: \"hello\"\n).insert\nmodel_id = model.id!\n\nputs MyModel.find_by_id(model_id).to_json\n# =\u003e \"{\\\"_id\\\":\\\"5ea052ce85ed2a2e1d0c87a2\\\",\\\"name\\\":\\\"hello\\\",\\\"count\\\":3}\"\n\nmodel.name = \"good night\"\nmodel.update\n\nputs MyModel.find_by_id(model_id).to_json\n# =\u003e \"{\\\"_id\\\":\\\"5ea052ce85ed2a2e1d0c87a2\\\",\\\"name\\\":\\\"good night\\\",\\\"count\\\":3}\"\n\nmodel.remove\nputs MyModel.count\n# =\u003e 0\n```\n\n### Running scripts\n\n[**API documentation**](https://elbywan.github.io/moongoon/Moongoon/Database/Scripts/Base.html)\n\n```crystal\n# A script must inherit from `Moongoon::Database::Scripts::Base`\n# Requiring the script before connecting to the database should be all it takes to register it.\n#\n# Scripts are then processed automatically.\nclass Moongoon::Database::Scripts::Test \u003c Moongoon::Database::Scripts::Base\n  # Scripts run in ascending order.\n  # Default order if not specified is 1.\n  order Time.utc(2020, 3, 11).to_unix\n\n  def process(db : Mongo::Database)\n    # Dummy code that will add a ban flag for users that are called 'John'.\n    # This code uses the `cryomongo` syntax, but Models could\n    # be used for convenience despite a small performance overhead.\n    db[\"users\"].update_many(\n      filter: {name: \"John\"},\n      update: {\"$set\": {\"banned\": true}}\n    )\n  end\nend\n```\n\n## Contributing\n\n1. Fork it (\u003chttps://github.com/elbywan/moongoon/fork\u003e)\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create a new Pull Request\n\n## Contributors\n\nSee the [contributors page](https://github.com/elbywan/moongoon/graphs/contributors).\n\n## Credit\n\n- Icon made by [Smashicons](https://www.flaticon.com/authors/smashicons) from [www.flaticon.com](https://www.flaticon.com).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felbywan%2Fmoongoon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felbywan%2Fmoongoon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felbywan%2Fmoongoon/lists"}