<div align="center"> <img src="icon.svg" width="128" height="128" /> <h1>moongoon</h1> <h3>A MongoDB ODM written in Crystal.</h3> <a href="https://travis-ci.org/elbywan/moongoon"><img alt="travis-badge" src="https://travis-ci.org/elbywan/moongoon.svg?branch=master"></a> <a href="https://github.com/elbywan/moongoon/tags"><img alt="GitHub tag (latest SemVer)" src="https://img.shields.io/github/v/tag/elbywan/moongoon"></a> <a href="https://github.com/elbywan/moongoon/blob/master/LICENSE"><img alt="GitHub" src="https://img.shields.io/github/license/elbywan/moongoon"></a> </div>
<hr/>
An object-document mapper (ODM) library written in Crystal which makes interacting with MongoDB a breeze.
This library relies on:
For the moongoon version relying on the mongo.cr driver, please check the mongo.cr branch.
Installation
- Add the dependency to your shard.yml:
dependencies:
  moongoon:
    github: elbywan/moongoon- Run shards install
- Profit! đź’°
Usage
Minimal working example
require "moongoon"
# A Model inherits from `Moongoon::Collection`
class User < Moongoon::Collection
  collection "users"
  index keys: { name: 1, age: 1 }, options: { unique: true }
  property name : String
  property age : Int32
  property pets : Array(Pet)
  # Nested models inherit from `Moongoon::Document`
  class Pet < Moongoon::Document
    property pet_name : String
  end
end
# Connect to the mongodb instance.
Moongoon.connect("mongodb://localhost:27017", database_name: "my_database")
# Initialize a model from arguments…
user = User.new(name: "Eric", age: 10, pets: [
  User::Pet.new(pet_name: "Mr. Kitty"),
  User::Pet.new(pet_name: "Fluffy")
])
# …or JSON data…
user = User.from_json(%(
  "name": "Eric",
  "age": 10,
  "pets": [
    { "pet_name": "Mr. Kitty" },
    { "pet_name": "Fluffy" }
  ]
))
# …or from querying the database.
user = User.find_one!({ name: "Eric" })
# Insert a model in the database.
user.insert
# Modify it.
user.name = "Kyle"
user.update
# Delete it.
user.removeConnecting
- Initial connection-instance-method)
- Hooks)-instance-method)
- Low-level
require "moongoon"
Moongoon.before_connect {
  puts "Connecting…"
}
Moongoon.after_connect {
  puts "Connected!"
}
# … #
Moongoon.connect(
  database_url: "mongodb://address:27017",
  database_name: "my_database"
)
# In case you need to perform a low level query, use `Moongoon.client` or `Moongoon.database`.
# Here, *db* is a `cryomongo` Mongo::Database. (For more details, check the `cryomongo` documentation)
db = Moongoon.database
cursor = db["my_collection"].list_indexes
puts cursor.to_a.to_jsonModels
- Indexes:Nil-class-method)
- Relationships-macro)
- Aggregations-class-method)
- Versioning-macro)
require "moongoon"
class MyModel < Moongoon::Collection
  collection "models"
  # Note: the database can be changed - if different from the default one
  # database "database_name"
  # Define indexes
  index keys: { name: 1 }
  # Specify agregation pipeline stages that will automatically be used for queries.
  aggregation_pipeline(
    {
      "$addFields": {
        count: {
          "$size": "$array"
        }
      }
    },
    {
      "$project": {
        array: 0
      }
    }
  )
  # Collection fields
  property name : String
  property count : Int32?
  property array : Array(Int32)? = [1, 2, 3]
end
# …assuming moongoon is connected… #
MyModel.clear
model = MyModel.new(
  name: "hello"
).insert
model_id = model.id!
puts MyModel.find_by_id(model_id).to_json
# => "{\"_id\":\"5ea052ce85ed2a2e1d0c87a2\",\"name\":\"hello\",\"count\":3}"
model.name = "good night"
model.update
puts MyModel.find_by_id(model_id).to_json
# => "{\"_id\":\"5ea052ce85ed2a2e1d0c87a2\",\"name\":\"good night\",\"count\":3}"
model.remove
puts MyModel.count
# => 0Running scripts
# A script must inherit from `Moongoon::Database::Scripts::Base`
# Requiring the script before connecting to the database should be all it takes to register it.
#
# Scripts are then processed automatically.
class Moongoon::Database::Scripts::Test < Moongoon::Database::Scripts::Base
  # Scripts run in ascending order.
  # Default order if not specified is 1.
  order Time.utc(2020, 3, 11).to_unix
  def process(db : Mongo::Database)
    # Dummy code that will add a ban flag for users that are called 'John'.
    # This code uses the `cryomongo` syntax, but Models could
    # be used for convenience despite a small performance overhead.
    db["users"].update_many(
      filter: {name: "John"},
      update: {"$set": {"banned": true}}
    )
  end
endContributing
- Fork it (<https://github.com/elbywan/moongoon/fork>)
- Create your feature branch (git checkout -b my-new-feature)
- Commit your changes (git commit -am 'Add some feature')
- Push to the branch (git push origin my-new-feature)
- Create a new Pull Request
Contributors
See the contributors page.
Credit
- Icon made by Smashicons from www.flaticon.com.