SlideShare a Scribd company logo
Schema-less Design
An introduction to the Mongoid ODM
1. MongoDB
2. Mongoid ODM compares to ORM/SQL
3. Modelling Bitmaker Rainforest app without
ActiveRecord
4. Going further
5. Conclusion
Overview
Questions going in
• What is MongoDB?
• How does it compare from SQL-based databases?
• What does schema-less entail?
• How does ODM compare with ORM? Rainforest
tutorial
• Worth it?
Object Document Mapper (ODM)
Translate between objects in code and document
representation of data.
Object Relational Mapping translates between
objects in code the the relational representation of
the data.
MongoDB
• Open-source database
• NoSQL (cluster friendly, 21st-century web, non-
relational, schema-less)
• Data is stored in collections and documents
whereas in SQL data is stored in tables and rows
• JSON-like structure to documents
Differs from SQL
No JOINS -> run two or more queries
Embed and Referencing of document/data objects
Fast querying
PostgreSQL has strict schema / MongoDB has
implicit schema
Use cases
“Big Data” - large and unwieldy
90% of business data is unstructured
Increasing volume, variety and velocity
craigslist, Forbes, New York Times, Foursquare, etc.
The Setup
Install mongodb
https://docs.mongodb.org/manual/installation/
Run mongo server and mongo database in separate
terminal tabs
~>rails new rainforest —skip-active-record
The Setup
Removes ActiveRecord from the application
No schema.rb
No migrations folder
gem 'mongoid', '~> 5.1'
~>bundle install
~>rails generate mongoid:config
creates config/mongoid.yml
application.rb
require File.expand_path('../boot', __FILE__)
require "rails"
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
# require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_view/railtie"
require "sprockets/railtie"
require "rails/test_unit/railtie"
. . .
mongoid.yml
development:
# Configure available database clients. (required)
clients:
# Defines the default client. (required)
default:
# Defines the name of the default database that Mongoid can
connect to.
# (required).
database: rainforest_development
# Provides the hosts the default client can connect to. Must
be an array
# of host:port pairs. (required)
hosts:
- localhost:27017
options:
# Change the default write concern. (default = { w: 1 })
# write:
# w: 1
Rainforest App
class Product
include Mongoid::Document
field :name, type: String
field :description, type: String
field :price_in_cents, type: Integer
. . .
embeds_many :reviews
embeds_one :category
end
class Category
include Mongoid::Document
field :name, type: String
embedded_in :product
end
Product Controller
class ProductsController < ApplicationController
. . .
def product_params
params.require(:product).permit(:name, :description, :price_
in_cents, {category: [:category_id, :name]})
end
end
Rainforest App
class User
include Mongoid::Document
field :name, type: String
field :email, type: String
field :password, type: String
. . .
has_many :products
end
class Review
include Mongoid::Document
field :comment, type: String
field :user_id, type: BSON::ObjectId
. . .
embedded_in :product
end
Relations
Mongoid ODM associations similar to ActiveRecord ORM
Association is not just for Relational Mappers
Embeds One, Embeds Many, Has One, Has Many, Has And
Belongs To Many, counter_cache (cache the counts of an
associated model)
No has_many :through
BSON Objects
BSON: supports embedding of objects within arrays
Allow for extensions not part of JSON spec
Minimum overhead
Traverse quickly (fast to encode and decode)
{
"_id" : ObjectId("5728b57b370d93124e000000"),
"name" : "Day planner",
"description" : "Schedule events",
"price_in_cents" : 1299,
"user_id" : ObjectId("5727b3b0370d93009d000000"),
"category" : {
"_id" : ObjectId("5728b57b370d93124e000001"),
"name" : “Office material"
},
"reviews" : [
{
"_id" : ObjectId("5728b5a3370d93124e000002"),
"comment" : "A great product",
"user_id" : ObjectId("5727b3b0370d93009d000000")
}
[1] pry(main)> Product.first
#<Product:0x007fc1290cd108> {
:_id => BSON::ObjectId('56b54bc3370d93d2d5411757'),
:category => {
"_id" => BSON::ObjectId('570c78f1370d936468000000'),
"name" => "Electronics"
},
:description => "Listen to music without all the hassle of a cord.",
:name => "Wireless Headphones",
:price_in_cents => 60,
:reviews => [
[0] {
"_id" => BSON::ObjectId('56b54e59370d93d3b4fe9848'),
"comment" => "Test comment”,
"user_id" => BSON::ObjectId('56eb9d92370d937950d21463
},
[1] {
"_id" => BSON::ObjectId('56b54e5f370d93d3b4fe9849'),
"comment" => "Checking commentrn”,
"user_id" => BSON::ObjectId('56eb9d92370d937950d21463
},
[2] {
"_id" => BSON::ObjectId('56b54e6d370d93d3b4fe984a'),
"comment" => "Just bought these headphones.”,
"user_id" => BSON::ObjectId('56eb9d92370d937950d21463
},
[0] {
"_id" => BSON::ObjectId('5706dc66370d934ccd000000'),
"comment" => "Checking embedded review",
"user_id" => BSON::ObjectId('56eb9d92370d937950d21463')
}
]
}
Rails Console
[3] pry(main)> products = Product.all
#<Mongoid::Criteria
selector: {}
options: {}
class: Product
embedded: false>
The query doesn’t run until the data is requested
[6] pry(main)> products.each {|product|puts product.name }
Wireless Headphones
Chromecast for TV
Ferrari
ATM
Computer
Ferrari2
Game Boy
Sony Headphones
Speakers
Car
Dell Computer
Samsung Television
Audi Convertible
Snowmobile
#<Mongoid::Contextual::Mongo:0x007fc129167550 @cache=nil, @klass=Product,
@criteria=#<Mongoid::Criteria
selector: {}
options: {}
class: Product
embedded: false>
, @collection=#<Mongo::Collection:0x70233797373000
namespace=rainforest_development.products>, @view=#<Mongo::Collection::View:0x70233797372780
namespace='rainforest_development.products @selector={} @options={}>, @cache_loaded=true>
Implicit schema
[9] pry(main)> product[:model] = "TS2-3Q78"
[8] pry(main)> product = Product.first
[1] pry(main)> Product.first
#<Product:0x007fc1290cd108> {
:_id => BSON::ObjectId('56b54bc3370d93d2d5411757'),
:category => {
"_id" => BSON::ObjectId('570c78f1370d936468000000'),
"name" => "Electronics"
},
:description => "Listen to music without all the hassle of a cord.",
:model => "TS2-3Q78",
:name => "Wireless Headphones",
:price_in_cents => 60,
:reviews => [
[0] {
"_id" => BSON::ObjectId('56b54e59370d93d3b4fe9848'),
"comment" => "Test comment"
},
[1] {
"_id" => BSON::ObjectId('56b54e5f370d93d3b4fe9849'),
"comment" => "Checking commentrn"
},
[2] {
"_id" => BSON::ObjectId('56b54e6d370d93d3b4fe984a'),
"comment" => "Just bought these headphones."
},
[3] {
"_id" => BSON::ObjectId('5706dc66370d934ccd000000'),
"comment" => "Checking embedded review",
"user_id" => BSON::ObjectId('56eb9d92370d937950d21463')
}
]
}
Mongoid
Similar syntax to ActiveRecord - associations, datatypes, etc.
No need for migrations
Great documentation; active community
Popular gems have mongoid counterpart (Devise,
carrierwave-mongoid, mongoid-paperclip, geocoder,
mongoid-rspec)
Setup is fast and mistakes quickly fixed (no rollbacks)
class Product
include Mongoid::Document
include Mongoid::Paperclip
. . .
has_mongoid_attached_file :avatar, styles: { medium: "300x300>",
thumb: "100x100>" }, default_url: lambda { |image|
ActionController::Base.helpers.asset_path('missing.png') }
validates_attachment_content_type :avatar,:content_type =>
["image/jpg",
"image/jpeg",
"image/png",
"image/gif"]
end
class ProductsController < ApplicationController
. . .
def product_params
params.require(:product).permit(:name, :description, :price_in_cents,
:avatar, {category: [:category_id, :name]})
end
#<Product:0x007fc12b0db148> {
:_id => BSON::ObjectId('570c32f9370d935b78000000'),
:avatar_content_type => "image/jpeg",
:avatar_file_name => "snowmobile.jpeg",
:avatar_file_size => 7081,
:avatar_fingerprint => "33234414813b3e3bf8a26281a2d7316f",
:avatar_updated_at => 2016-04-12 00:56:31 UTC,
:category => {
"_id" => BSON::ObjectId('570c32f9370d935b78000001'),
"name" => "Automobile"
},
:description => "For northern living",
:name => "Snowmobile",
:price_in_cents => 345436
}
Going further
• Indexing
• Map/Reduce to condense large volumes of data; work
around for JOINS - rearrange data into aggregate
forms
• Sharding
• Track data versioning
• GeoSpatial indexing
Worth it?
• It depends what you want
• Have MongoDB serve up user info or cache preferences, integrate with social
networks; SQL to handle payments/ordering
• Great for searching large amounts of data.
• PostgreSQL JSON type - support for arbitrary attributes (WARNING: anti-pattern)
• For this application, mongoid can work and clarified features for me, but SQL
and Schema-based design seem optimized for this case
• Different ways to organize data and design models
• Learned some new things about ActiveRecord and PostgreSQL
Sources
https://www.mongodb.com/nosql-explained
Rege, Gautam. Ruby and MongoDB Web Development Beginner’s Guide, Packt
Publishing, 2012
http://www.sarahmei.com/blog/2013/11/11/why-you-should-never-use-mongodb/
comment-page-1/
https://www.mongodb.com/compare/mongodb-mysql
https://github.com/meskyanichi/mongoid-paperclip
https://gorails.com/guides/setting-up-rails-4-with-mongodb-and-mongoid
https://gorails.com/blog/rails-4-0-with-mongodb-and-mongoid
http://stackoverflow.com/questions/26182890/perform-atomic-block-transactions-in-
rails-with-mongoid
http://blog.2ndquadrant.com/postgresql-anti-patterns-unnecessary-jsonhstore-
dynamic-columns/
@MrNickAltobelli
nmhalt@gmail.com
github: DataNick
www.nickaltobelli.com
Thank You!

More Related Content

What's hot (18)

PDF
Mongo DB schema design patterns
joergreichert
 
PPTX
MongoDB San Francisco 2013: Data Modeling Examples From the Real World presen...
MongoDB
 
PPT
Building web applications with mongo db presentation
Murat Çakal
 
PPTX
MongoDB Schema Design: Four Real-World Examples
Mike Friedman
 
PDF
MongoDB Schema Design
Alex Litvinok
 
PDF
Map/Confused? A practical approach to Map/Reduce with MongoDB
Uwe Printz
 
PPTX
Data Modeling for the Real World
Mike Friedman
 
KEY
MongoDB, PHP and the cloud - php cloud summit 2011
Steven Francia
 
PPTX
Webinar: Back to Basics: Thinking in Documents
MongoDB
 
PPTX
MongoDB Advanced Schema Design - Inboxes
Jared Rosoff
 
PPTX
Webinar: Data Modeling Examples in the Real World
MongoDB
 
PPTX
MongoDB + Java - Everything you need to know
Norberto Leite
 
PPTX
Indexing Strategies to Help You Scale
MongoDB
 
PDF
10gen Presents Schema Design and Data Modeling
DATAVERSITY
 
PDF
Dealing with Azure Cosmos DB
Mihail Mateev
 
PPTX
Back to Basics Webinar 3: Schema Design Thinking in Documents
MongoDB
 
PPTX
Building Your First Application with MongoDB
MongoDB
 
PPTX
Webinar: Schema Design
MongoDB
 
Mongo DB schema design patterns
joergreichert
 
MongoDB San Francisco 2013: Data Modeling Examples From the Real World presen...
MongoDB
 
Building web applications with mongo db presentation
Murat Çakal
 
MongoDB Schema Design: Four Real-World Examples
Mike Friedman
 
MongoDB Schema Design
Alex Litvinok
 
Map/Confused? A practical approach to Map/Reduce with MongoDB
Uwe Printz
 
Data Modeling for the Real World
Mike Friedman
 
MongoDB, PHP and the cloud - php cloud summit 2011
Steven Francia
 
Webinar: Back to Basics: Thinking in Documents
MongoDB
 
MongoDB Advanced Schema Design - Inboxes
Jared Rosoff
 
Webinar: Data Modeling Examples in the Real World
MongoDB
 
MongoDB + Java - Everything you need to know
Norberto Leite
 
Indexing Strategies to Help You Scale
MongoDB
 
10gen Presents Schema Design and Data Modeling
DATAVERSITY
 
Dealing with Azure Cosmos DB
Mihail Mateev
 
Back to Basics Webinar 3: Schema Design Thinking in Documents
MongoDB
 
Building Your First Application with MongoDB
MongoDB
 
Webinar: Schema Design
MongoDB
 

Similar to Using Mongoid with Ruby on Rails (20)

PPTX
Simple MongoDB design for Rails apps
Sérgio Santos
 
PDF
Mongodb mongoid
Marcos Vanetta
 
ODP
Seth Edwards on MongoDB
Skills Matter
 
ODP
LRUG Presentation
SethEdwards
 
PDF
Mongo db eveningschemadesign
MongoDB APAC
 
PDF
MongoDB at FrozenRails
Mike Dirolf
 
PDF
Build your first MongoDB App in Ruby @ StrangeLoop 2013
Steven Francia
 
PPTX
Rails with MongoDB - RORLab 47th
Eugene Park
 
KEY
Practical Ruby Projects With Mongo Db
Alex Sharp
 
PPTX
Conceptos básicos. seminario web 3 : Diseño de esquema pensado para documentos
MongoDB
 
PDF
Mongodb
Scott Motte
 
KEY
MongoDB - Ruby document store that doesn't rhyme with ouch
Wynn Netherland
 
PDF
Building your first app with MongoDB
Norberto Leite
 
ODP
Mongodb With Mongoid
Marcos Vanetta
 
KEY
The Ruby/mongoDB ecosystem
Harold Giménez
 
KEY
Benefits of using MongoDB: Reduce Complexity & Adapt to Changes
Alex Nguyen
 
PDF
Using MongoDB and a Relational Database at MongoDB Day
hayesdavis
 
PPT
No SQL and MongoDB - Hyderabad Scalability Meetup
Hyderabad Scalability Meetup
 
PDF
Mongodb Introduction
Raghvendra Parashar
 
PDF
MongoDB: a gentle, friendly overview
Antonio Pintus
 
Simple MongoDB design for Rails apps
Sérgio Santos
 
Mongodb mongoid
Marcos Vanetta
 
Seth Edwards on MongoDB
Skills Matter
 
LRUG Presentation
SethEdwards
 
Mongo db eveningschemadesign
MongoDB APAC
 
MongoDB at FrozenRails
Mike Dirolf
 
Build your first MongoDB App in Ruby @ StrangeLoop 2013
Steven Francia
 
Rails with MongoDB - RORLab 47th
Eugene Park
 
Practical Ruby Projects With Mongo Db
Alex Sharp
 
Conceptos básicos. seminario web 3 : Diseño de esquema pensado para documentos
MongoDB
 
Mongodb
Scott Motte
 
MongoDB - Ruby document store that doesn't rhyme with ouch
Wynn Netherland
 
Building your first app with MongoDB
Norberto Leite
 
Mongodb With Mongoid
Marcos Vanetta
 
The Ruby/mongoDB ecosystem
Harold Giménez
 
Benefits of using MongoDB: Reduce Complexity & Adapt to Changes
Alex Nguyen
 
Using MongoDB and a Relational Database at MongoDB Day
hayesdavis
 
No SQL and MongoDB - Hyderabad Scalability Meetup
Hyderabad Scalability Meetup
 
Mongodb Introduction
Raghvendra Parashar
 
MongoDB: a gentle, friendly overview
Antonio Pintus
 
Ad

Recently uploaded (20)

PDF
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
PDF
UPDF - AI PDF Editor & Converter Key Features
DealFuel
 
PDF
Mastering Financial Management in Direct Selling
Epixel MLM Software
 
PDF
SIZING YOUR AIR CONDITIONER---A PRACTICAL GUIDE.pdf
Muhammad Rizwan Akram
 
DOCX
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
PPTX
The Project Compass - GDG on Campus MSIT
dscmsitkol
 
PDF
Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
PDF
Transcript: Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
DOCX
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
PDF
The Rise of AI and IoT in Mobile App Tech.pdf
IMG Global Infotech
 
PPTX
Mastering ODC + Okta Configuration - Chennai OSUG
HathiMaryA
 
PPTX
Agentforce World Tour Toronto '25 - MCP with MuleSoft
Alexandra N. Martinez
 
PDF
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
PPT
Ericsson LTE presentation SEMINAR 2010.ppt
npat3
 
PPTX
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
PDF
“Squinting Vision Pipelines: Detecting and Correcting Errors in Vision Models...
Edge AI and Vision Alliance
 
PDF
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
PDF
Kit-Works Team Study_20250627_한달만에만든사내서비스키링(양다윗).pdf
Wonjun Hwang
 
PDF
Peak of Data & AI Encore AI-Enhanced Workflows for the Real World
Safe Software
 
PDF
What’s my job again? Slides from Mark Simos talk at 2025 Tampa BSides
Mark Simos
 
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
UPDF - AI PDF Editor & Converter Key Features
DealFuel
 
Mastering Financial Management in Direct Selling
Epixel MLM Software
 
SIZING YOUR AIR CONDITIONER---A PRACTICAL GUIDE.pdf
Muhammad Rizwan Akram
 
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
The Project Compass - GDG on Campus MSIT
dscmsitkol
 
Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
Transcript: Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
The Rise of AI and IoT in Mobile App Tech.pdf
IMG Global Infotech
 
Mastering ODC + Okta Configuration - Chennai OSUG
HathiMaryA
 
Agentforce World Tour Toronto '25 - MCP with MuleSoft
Alexandra N. Martinez
 
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
Ericsson LTE presentation SEMINAR 2010.ppt
npat3
 
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
“Squinting Vision Pipelines: Detecting and Correcting Errors in Vision Models...
Edge AI and Vision Alliance
 
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
Kit-Works Team Study_20250627_한달만에만든사내서비스키링(양다윗).pdf
Wonjun Hwang
 
Peak of Data & AI Encore AI-Enhanced Workflows for the Real World
Safe Software
 
What’s my job again? Slides from Mark Simos talk at 2025 Tampa BSides
Mark Simos
 
Ad

Using Mongoid with Ruby on Rails

  • 2. 1. MongoDB 2. Mongoid ODM compares to ORM/SQL 3. Modelling Bitmaker Rainforest app without ActiveRecord 4. Going further 5. Conclusion Overview
  • 3. Questions going in • What is MongoDB? • How does it compare from SQL-based databases? • What does schema-less entail? • How does ODM compare with ORM? Rainforest tutorial • Worth it?
  • 4. Object Document Mapper (ODM) Translate between objects in code and document representation of data. Object Relational Mapping translates between objects in code the the relational representation of the data.
  • 5. MongoDB • Open-source database • NoSQL (cluster friendly, 21st-century web, non- relational, schema-less) • Data is stored in collections and documents whereas in SQL data is stored in tables and rows • JSON-like structure to documents
  • 6. Differs from SQL No JOINS -> run two or more queries Embed and Referencing of document/data objects Fast querying PostgreSQL has strict schema / MongoDB has implicit schema
  • 7. Use cases “Big Data” - large and unwieldy 90% of business data is unstructured Increasing volume, variety and velocity craigslist, Forbes, New York Times, Foursquare, etc.
  • 9. ~>rails new rainforest —skip-active-record The Setup Removes ActiveRecord from the application No schema.rb No migrations folder gem 'mongoid', '~> 5.1' ~>bundle install ~>rails generate mongoid:config creates config/mongoid.yml
  • 10. application.rb require File.expand_path('../boot', __FILE__) require "rails" # Pick the frameworks you want: require "active_model/railtie" require "active_job/railtie" # require "active_record/railtie" require "action_controller/railtie" require "action_mailer/railtie" require "action_view/railtie" require "sprockets/railtie" require "rails/test_unit/railtie" . . .
  • 11. mongoid.yml development: # Configure available database clients. (required) clients: # Defines the default client. (required) default: # Defines the name of the default database that Mongoid can connect to. # (required). database: rainforest_development # Provides the hosts the default client can connect to. Must be an array # of host:port pairs. (required) hosts: - localhost:27017 options: # Change the default write concern. (default = { w: 1 }) # write: # w: 1
  • 12. Rainforest App class Product include Mongoid::Document field :name, type: String field :description, type: String field :price_in_cents, type: Integer . . . embeds_many :reviews embeds_one :category end class Category include Mongoid::Document field :name, type: String embedded_in :product end
  • 13. Product Controller class ProductsController < ApplicationController . . . def product_params params.require(:product).permit(:name, :description, :price_ in_cents, {category: [:category_id, :name]}) end end
  • 14. Rainforest App class User include Mongoid::Document field :name, type: String field :email, type: String field :password, type: String . . . has_many :products end class Review include Mongoid::Document field :comment, type: String field :user_id, type: BSON::ObjectId . . . embedded_in :product end
  • 15. Relations Mongoid ODM associations similar to ActiveRecord ORM Association is not just for Relational Mappers Embeds One, Embeds Many, Has One, Has Many, Has And Belongs To Many, counter_cache (cache the counts of an associated model) No has_many :through
  • 16. BSON Objects BSON: supports embedding of objects within arrays Allow for extensions not part of JSON spec Minimum overhead Traverse quickly (fast to encode and decode)
  • 17. { "_id" : ObjectId("5728b57b370d93124e000000"), "name" : "Day planner", "description" : "Schedule events", "price_in_cents" : 1299, "user_id" : ObjectId("5727b3b0370d93009d000000"), "category" : { "_id" : ObjectId("5728b57b370d93124e000001"), "name" : “Office material" }, "reviews" : [ { "_id" : ObjectId("5728b5a3370d93124e000002"), "comment" : "A great product", "user_id" : ObjectId("5727b3b0370d93009d000000") }
  • 18. [1] pry(main)> Product.first #<Product:0x007fc1290cd108> { :_id => BSON::ObjectId('56b54bc3370d93d2d5411757'), :category => { "_id" => BSON::ObjectId('570c78f1370d936468000000'), "name" => "Electronics" }, :description => "Listen to music without all the hassle of a cord.", :name => "Wireless Headphones", :price_in_cents => 60, :reviews => [ [0] { "_id" => BSON::ObjectId('56b54e59370d93d3b4fe9848'), "comment" => "Test comment”, "user_id" => BSON::ObjectId('56eb9d92370d937950d21463 }, [1] { "_id" => BSON::ObjectId('56b54e5f370d93d3b4fe9849'), "comment" => "Checking commentrn”, "user_id" => BSON::ObjectId('56eb9d92370d937950d21463 }, [2] { "_id" => BSON::ObjectId('56b54e6d370d93d3b4fe984a'), "comment" => "Just bought these headphones.”, "user_id" => BSON::ObjectId('56eb9d92370d937950d21463 }, [0] { "_id" => BSON::ObjectId('5706dc66370d934ccd000000'), "comment" => "Checking embedded review", "user_id" => BSON::ObjectId('56eb9d92370d937950d21463') } ] }
  • 19. Rails Console [3] pry(main)> products = Product.all #<Mongoid::Criteria selector: {} options: {} class: Product embedded: false> The query doesn’t run until the data is requested
  • 20. [6] pry(main)> products.each {|product|puts product.name } Wireless Headphones Chromecast for TV Ferrari ATM Computer Ferrari2 Game Boy Sony Headphones Speakers Car Dell Computer Samsung Television Audi Convertible Snowmobile #<Mongoid::Contextual::Mongo:0x007fc129167550 @cache=nil, @klass=Product, @criteria=#<Mongoid::Criteria selector: {} options: {} class: Product embedded: false> , @collection=#<Mongo::Collection:0x70233797373000 namespace=rainforest_development.products>, @view=#<Mongo::Collection::View:0x70233797372780 namespace='rainforest_development.products @selector={} @options={}>, @cache_loaded=true>
  • 21. Implicit schema [9] pry(main)> product[:model] = "TS2-3Q78" [8] pry(main)> product = Product.first
  • 22. [1] pry(main)> Product.first #<Product:0x007fc1290cd108> { :_id => BSON::ObjectId('56b54bc3370d93d2d5411757'), :category => { "_id" => BSON::ObjectId('570c78f1370d936468000000'), "name" => "Electronics" }, :description => "Listen to music without all the hassle of a cord.", :model => "TS2-3Q78", :name => "Wireless Headphones", :price_in_cents => 60, :reviews => [ [0] { "_id" => BSON::ObjectId('56b54e59370d93d3b4fe9848'), "comment" => "Test comment" }, [1] { "_id" => BSON::ObjectId('56b54e5f370d93d3b4fe9849'), "comment" => "Checking commentrn" }, [2] { "_id" => BSON::ObjectId('56b54e6d370d93d3b4fe984a'), "comment" => "Just bought these headphones." }, [3] { "_id" => BSON::ObjectId('5706dc66370d934ccd000000'), "comment" => "Checking embedded review", "user_id" => BSON::ObjectId('56eb9d92370d937950d21463') } ] }
  • 23. Mongoid Similar syntax to ActiveRecord - associations, datatypes, etc. No need for migrations Great documentation; active community Popular gems have mongoid counterpart (Devise, carrierwave-mongoid, mongoid-paperclip, geocoder, mongoid-rspec) Setup is fast and mistakes quickly fixed (no rollbacks)
  • 24. class Product include Mongoid::Document include Mongoid::Paperclip . . . has_mongoid_attached_file :avatar, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: lambda { |image| ActionController::Base.helpers.asset_path('missing.png') } validates_attachment_content_type :avatar,:content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"] end class ProductsController < ApplicationController . . . def product_params params.require(:product).permit(:name, :description, :price_in_cents, :avatar, {category: [:category_id, :name]}) end
  • 25. #<Product:0x007fc12b0db148> { :_id => BSON::ObjectId('570c32f9370d935b78000000'), :avatar_content_type => "image/jpeg", :avatar_file_name => "snowmobile.jpeg", :avatar_file_size => 7081, :avatar_fingerprint => "33234414813b3e3bf8a26281a2d7316f", :avatar_updated_at => 2016-04-12 00:56:31 UTC, :category => { "_id" => BSON::ObjectId('570c32f9370d935b78000001'), "name" => "Automobile" }, :description => "For northern living", :name => "Snowmobile", :price_in_cents => 345436 }
  • 26. Going further • Indexing • Map/Reduce to condense large volumes of data; work around for JOINS - rearrange data into aggregate forms • Sharding • Track data versioning • GeoSpatial indexing
  • 27. Worth it? • It depends what you want • Have MongoDB serve up user info or cache preferences, integrate with social networks; SQL to handle payments/ordering • Great for searching large amounts of data. • PostgreSQL JSON type - support for arbitrary attributes (WARNING: anti-pattern) • For this application, mongoid can work and clarified features for me, but SQL and Schema-based design seem optimized for this case • Different ways to organize data and design models • Learned some new things about ActiveRecord and PostgreSQL
  • 28. Sources https://www.mongodb.com/nosql-explained Rege, Gautam. Ruby and MongoDB Web Development Beginner’s Guide, Packt Publishing, 2012 http://www.sarahmei.com/blog/2013/11/11/why-you-should-never-use-mongodb/ comment-page-1/ https://www.mongodb.com/compare/mongodb-mysql https://github.com/meskyanichi/mongoid-paperclip https://gorails.com/guides/setting-up-rails-4-with-mongodb-and-mongoid https://gorails.com/blog/rails-4-0-with-mongodb-and-mongoid http://stackoverflow.com/questions/26182890/perform-atomic-block-transactions-in- rails-with-mongoid http://blog.2ndquadrant.com/postgresql-anti-patterns-unnecessary-jsonhstore- dynamic-columns/