- Notifications
You must be signed in to change notification settings - Fork6
Mongo ORM: A simple ORM for using MongoDB with the crystal programming language, designed for use with Amber. Based loosely on Granite ORM. Supports Rails-esque models, associations and embedded documents.
License
sam0x17/mongo_orm
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
This shard provides a basic ORM for using MongoDB wth the Crystal programming language.Mongo ORM is based onGranite ORM,and provides basic querying, associations, and model lifecycle capabilities. Mongo ORMis intended to be used with theAmber Framework,but can be used with vanilla crystal or any web framework.
Suggestions, feature requests, bug fixes, and pull requests are always welcome.
First you will need toinstall MongoDB(unless you are running a remote server), as well as the dependencies forMongo.cr. On Arch Linux and Ubuntu,this can be done using your package manager as shown below. For other linux distrubutions, you may be ableto use the script shown below.
Simply run:
$ sudo pacman -Syu libbson mongodb$ sudo systemctl start mongodb
Simply run:
sudo apt updatesudo apt install libmongoc-dev libmongoc-1.0-0 libmongoclient-dev
Simply run./install_linux_deps
, the contents of which are shown below:
# install_linux_deps.sh#!/bin/bashmkdir -p lib||exit 1cd lib||exit 1wget https://github.com/mongodb/mongo-c-driver/releases/download/1.1.0/mongo-c-driver-1.1.0.tar.gz||exit 1tar -zxvf mongo-c-driver-1.1.0.tar.gz&&cd mongo-c-driver-1.1.0/||exit 1./configure --prefix=/usr --libdir=/usr/lib||exit 1make -j4||exit 1sudo make install -j4||exit 1
You can just run./install_macos_deps
, the contents of which are shown below:
#!/bin/bashcurl -LO https://github.com/mongodb/mongo-c-driver/releases/download/1.9.4/mongo-c-driver-1.9.4.tar.gz||exit 1tar xzf mongo-c-driver-1.9.4.tar.gz||exit 1cd mongo-c-driver-1.9.4||exit 1./configure||exit 1make||exit 1sudo make install||exit 1
Next, add the following to theshard.yml
file in your project and runshards install
:
# shard.ymldependencies:mongo_orm:github:sam0x17/mongo_orm
By default (with zero configuration), Mongo ORM will attempt to connect to a databaserunning atlocalhost:27017
which is the default MongoDB port, with the databasenamemonogo_orm_db
.
If the environment variableDATABASE_URL
is present, Mongo ORM will connect usingthis variable instead. You can also specify the database name using theDATABASE_NAME
environment variable. For example:
$ DATABASE_URL=mongodb://localhost:11771;DATABASE_NAME=my_db crystal app.cr
If theDATABASE_URL
environment variable is not present, Mongo ORM will look for thefileconfig/database.yml
within your project directory. If the file exists, MongoORM will expect the following format (specify the keysdatabase_url
anddatabase_name
):
# config/database.ymldatabase_url:mongodb://localhost:11771database_name:my_db
MongoDB is different from conventional relational database systems mainly because thereis no set-in-stone schema, but instead a wilderness of BSON-based "documents" thatmay or may not roughly follow the same schema. Declaring static fields works much thesame as it does in Granite ORM:
require"mongo_orm"classUser <Mongo::ORM::Document field name :String field age :Int32 field deleted_at :Time field turned_on :Bool timestampsend
This will declare a model calledUser
with a string field calledname
, a 32-bitinteger field calledage
, a Time field calleddeleted_at
, a boolean field calledturned_on
, and the standardcreated_at
andupdated_at
fields you will recognizefrom Rails that are created because we specifiedtimestamps
.
Note: all Time fields are presently locked into UTC because of some conversion bugsthat arise when changing time zones and converting between BSON and crystal models.
To instantiate aUser
and save it to the database, you can do:
user=User.newuser.name="Sam"user.age=248user.turned_on=trueuser.save!puts user.inspect# print the created userputs"id:#{user._id}"# print the ID of the created user
Note that theID
field is named_id
, as in standard MongoDB.
You can also use the more compactcreate
notation:
user=User.createname:"Sam",age:248,turned_on:true
Currently, you can definehas_many
associations directly on a model, and they willbehave roughly the same way they would in standard Rails. For example:
classGroup <Mongo::ORM::Document field name :String has_many:usersend
This defines another model calledGroup
. A group has a String fieldname
, andhas an ID-based collection ofUser
documents calledusers
which can be accessedviagroup.users
wheregroup
is an instance ofGroup
. To make aUser
a memberof aGroup
,user.group_id
can be set to the document ID of an already-createdGroup
. Note that when you specify that model Ahas_many
model B, theb.a_id
fieldis also automatically created.
In addition to conventional table-style models/documents, Mongo ORM supports theability to embed documents or collections of documents within documents, as per theBSON standard. This is sometimes a more convenient or more efficient alternativeto spreading data out across multiple document collections (tables) and fully leveragesthe document-based nature of MongoDB. Note that you can also nest embedded documents.See the example below:
classTopic <Mongo::ORM::Document embeds top_comment :Comment# e.g. topic.top_comment.bodyendclassTag <Mongo::ORM::EmbeddedDocument field topic :StringendclassComment <Mongo::ORM::EmbeddedDocument field body :String embeds_many:tags# e.g. comment.tags[0]end
Mongo ORM also allows you to make use of document fields that are not specifiedexplicitly in the model schema. In fact, it is possible to use Mongo ORM withoutspecifying any model schema at all, however we have provided both options, as schemasprovide sane defaults, type checking, and consistency, whereas extended fields (ourname for fields not specified in a model schema) make it easy to do dynamic thingsthat would be difficult or impossible in traditional relational databases, and requirezero configuration.
For example, suppose you have anAdmin
collection in your database, and that some(but not all)Admin
documents have a field calledalias
:
admin=Admin.find(4)puts admin.alias
If the document does indeed have a field namedalias
, then this will printits value. If such a field is not defined, thennil
(nothing) will be printed. Thiswill also work on nested documents, for exampleblog.header.tag
whereblog
is aBlog
document andheader
is aHeader
embedded document.
If you know for a fact thatalias
should be defined on this particular document,you can use the following syntax to be more explicit:
admin=Admin.find(4)puts admin.alias!
The!
syntax will cause an error to be thrown (undefined method) in the event thatthealias
field is not defined.
About
Mongo ORM: A simple ORM for using MongoDB with the crystal programming language, designed for use with Amber. Based loosely on Granite ORM. Supports Rails-esque models, associations and embedded documents.