simple mongodb design for rails apps
DESCRIPTION
Introduction to MongoDB, Rails Mongoid ORM and some data modelling examples.TRANSCRIPT
Simple MongoDB design for Web (Rails) apps
Sérgio Santos@sdsantos
Improve Coimbra
Introduction / Disclamer
Bundlr MongoDB stats
MongoDB from the start
~ 3½ years of development
~ 6 GB of data
~ 6 million documents
Cloud hosted on MongoHQ
Burocracia MongoDB stats~ 3 weekends of development
~ 300MB of data
~ 721 documents
~ 400KB per document
Cloud hosted on MongoLab
Why MongoDB?
MongoDB 101
Documents
Collections
References
Embeds
Rails MongoDB ORMs
Mongoid vs MongoMapper
Mongoid
Modelsclass Person include Mongoid::Documentend
person = Person.newperson[:name] = 'Sérgio'person[:age] = 26person.save
Modelsclass Person include Mongoid::Document field :name, type: String field :age, type: Integerend
person = Person.newperson.name = 'Sérgio'person.age = 26person.save
Persistenceperson = Person.create(name: 'Sérgio', age: 26)
person.update_attributes(name: 'Sérgio Santos')
person.touch
person.delete
person.destroy
person.rename(:name, :first_name)
Queryingperson = Person.find("4baa56f1230048567300485c")
people = Person.where(age: 18)
people = Person.where(name: 'Sérgio').not(age: 26)
Person.count
Person.all.avg(:age)
-- INSERT MAP/REDUCE CLEVER EXAMPLE HERE --
Referencesclass Band include Mongoid::Document has_many :membersend
class Member include Mongoid::Document field :name, type: String belongs_to :bandend
References# The parent band document.{ "_id" : ObjectId("4d3ed089fb60ab534684b7e9")}
# The child member document. { "_id" : ObjectId("4d3ed089fb60ab534684b7f1"), "name" : "Matt Berninger" "band_id" : ObjectId("4d3ed089fb60ab534684b7e9")}
Embedsclass Band include Mongoid::Document embeds_many :albumsend
class Album include Mongoid::Document field :name, type: String embedded_in :bandend
Embeds{ "_id" : ObjectId("4d3ed089fb60ab534684b7e9"), "albums" : [ { "_id" : ObjectId("4d3ed089fb60ab534684b7e0"), "name" : "Boxer", } ]}
Extras
timestamps
identity map & cache
paranoia
versioning
Cloud Hosting
The Nice Stuff
No need to create the collection
class Band include Mongoid::Documentend
Store anythingclass ParamsStore include Mongoid::Documentend
class ApplicationController < ActionController::Base before_filter do Stuff.create(params) endend
Store long stuffclass Website include Mongoid::Document field :html, type: String field :css, type: String field :javascript, type: String embeds_many :imagesend
class Image include Mongoid::Document field :size, type: Integer field :file, type: Moped::BSON::Binary embedded_in :websiteend
Geoclass Person include Mongoid::Document field :location, :type => Array index( { location: Mongo::GEO2D }, { min: -180, max: 180 } )end
coimbra_location = [20, -8]Person.geo_near(coimbra_location).spherical
Full text searchclass Document include Mongoid::Document field :content, :type => String index( {:content => 'text'}, {:default_language => 'portuguese’} )end
Document.text_search('IKEA')
Caveats (not so nice)No joins
Impact of key length
No integrity checks for references
Document size limit of 16MB
Nesting depth limit of 100
( Bundlr ) Examples
Settingsclass User include Mongoid::Document embeds_one :settingsend
class Settings include Mongoid:Document field :receive_emails, type: Boolean field :theme, type: Symbol embedded_in :userend
Oauthsclass User include Mongoid::Document embeds_many :oauths index [["oauths.provider", Mongo::ASCENDING], ["oauths.uid", Mongo::ASCENDING]]end
class Oauth include Mongoid:Document field :provider, type: String field :token, type: String field :secret, type: String field :uid, type: String embedded_in :userend
Activity Streamclass Activity include Mongoid::Document include Mongoid::Timestamps
field :verb, :type => Symbol field :actor, :type => Hash field :object, :type => Hash field :target, :type => Hash field :receivers, :type => Array embeds_many :likesend
Relationshipsclass User include Mongoid::Document has_and_belongs_to_many :followers, :class_name => "User", :inverse_of => :followed_usersend
{ _id: ObjectId("4d541f6823380f670d000008"), follower_ids: [ ObjectId("4d4ea8ec86d56d2907000003"), ObjectId("50fe17c226c1b7000200018a") ],}
Need smarter relationships? Embed them!
Other examples
Model hierarchy
Migrations
Changing schema?
No right way of doing things… is all about
context!
Wrapping up…