SlideShare a Scribd company logo
1 of 74
Download to read offline
MongoDB & Harmony
Real World Usage of MongoDB




MongoSF, San Francisco        Steve Smith
April 30, 2010                  Ordered List
Hello!
steve@orderedlist.com
@orderedlist
http://orderedlist.com
http://get.harmonyapp.com
Things to Cover
1. What is Harmony?
2. Multiple Item Types
3. Completely Custom Data
4. Images and Files
5. Activity Streams
6. Wrap Up
What is Harmony?
Understanding Storage Needs
Harmony is for

Building Websites
Harmony is design to

Be Flexible
Harmony is designed to

Store Web Content
Demo Time
Things to Cover
1. What is Harmony?
2. Multiple Item Types
3. Completely Custom Data
4. Images and Files
5. Activity Streams
6. Wrap Up
Multiple Item Types
Flexibility in Collections
Harmony has

Pages
Harmony has

Blogs
Harmony has

Blog Posts
Harmony has

Blog Labels and
Archives
Harmony has

Many More Types...
All These Things

Have a URL
We Use

Single Collection
Inheritance
class Item
  include MongoMapper::Document

  key :_type,           String,     :index    => true
  key :title,           String,     :required => true
  key :path,            String,     :required => true, :index => true
  key :template_name,   String
  key :published_at,    Time
  key :parent_id,       ObjectId,   :index      =>   true
  key :parent_ids,      Array,      :index      =>   true
  key :site_id,         ObjectId,   :required   =>   true, :index => true
  key :nav_item,        Boolean,    :default    =>   true
  key :asset_ids,       Array,      :index      =>   true
  timestamps!
  userstamps!

  # more code here

end
class Page < Item

  key :position, Integer, :default => 1

  # more code here

end
class Blog < Item

  key :position,                   Integer, :default => 1
  key :labels_as,                  String, :default => 'tags'
  key :custom_permalink_structure, String

  # more code here

end
class BlogPost < Item

  key   :accepting_comments,   Boolean, :default => true
  key   :labels,               Set,     :index => true
  key   :year_id,              ObjectId
  key   :month_id,             ObjectId
  key   :day_id,               ObjectId

  # more code here

end
Separation of Code into

Meaningful Keys
One Collection Means

Simple Querying
Things to Cover
1. What is Harmony?
2. Multiple Item Types
3. Completely Custom Data
4. Images and Files
5. Activity Streams
6. Wrap Up
Custom Data
Unknown Possibilities
Every Item in Harmony gets

A Title and a Path
All Other Data is

Defined by the User
templates
templates
Template 1




Template 2




Template 3
templates    fields
Template 1




Template 2




Template 3
templates    fields
Template 1   Field 1


             Field 2


             Field 3

Template 2   Field 4


             Field 5


             Field 6

Template 3   Field 7


             Field 8


             Field 9
This data is not related, it

Belongs Together
templates
Template 1
  Field 1

  Field 2

  Field 3


Template 2
             Use Embedded
  Field 4    Documents
  Field 5

  Field 6


Template 3
  Field 7

  Field 8

  Field 9
items
items
Item 1




Item 2




Item 3
items    data
Item 1




Item 2




Item 3
items    data
Item 1   Data 1


         Data 2


         Data 3

Item 2   Data 4


         Data 5


         Data 6

Item 3   Data 7


         Data 8


         Data 9
items      templates
Item 1     Template 1
  Data 1     Field 1

  Data 2     Field 2

  Data 3     Field 3


Item 2     Template 2
  Data 4     Field 4

  Data 5     Field 5

  Data 6     Field 6


Item 3     Template 3
  Data 7     Field 7

  Data 8     Field 8

  Data 9     Field 9
class Template
  include MongoMapper::Document

  key :filename, String,   :index => true
  key :theme_id, ObjectId, :index => true
  key :contents, String
  timestamps!
  userstamps!

  many :fields

  # more code here

end
class Field
  include MongoMapper::EmbeddedDocument

  key   :name,            String, :required => true
  key   :key,             String, :required => true
  key   :field_type_id,   Integer, :required => true
  key   :help_text,       String
  key   :settings,        Hash
  key   :required,        Boolean

  embedded_in :template

  # more code here

end
class Item
  include MongoMapper::Document

  key :_type,           String,     :index    => true
  key :title,           String,     :required => true
  key :path,            String,     :required => true, :index => true
  key :template_name,   String
  key :published_at,    Time
  key :parent_id,       ObjectId,   :index      =>   true
  key :parent_ids,      Array,      :index      =>   true
  key :site_id,         ObjectId,   :required   =>   true, :index => true
  key :nav_item,        Boolean,    :default    =>   true
  key :asset_ids,       Array,      :index      =>   true
  timestamps!
  userstamps!

  many :data

  # more code here

end
class Datum
  include MongoMapper::EmbeddedDocument

  key :key,         String, :required => true, :length => 2..100
  key :file_upload, Boolean, :default => false
  key :value

  embedded_in :item

  # more code here

end
Embedding allows

Maximum Flexibility
Embedding allows

Keeping Data Together
Things to Cover
1. What is Harmony?
2. Multiple Item Types
3. Completely Custom Data
4. Images and Files
5. Activity Streams
6. Wrap Up
Images and Files
Binary Data Storage
Harmony contains several

Types of Files
Harmony contains

Text Files
Stylesheets, JavaScripts, Includes,
and Templates
Harmony contains

Binary Files
Images, File Uploads
All these are

Stored in Mongo
class Stylesheet
  include MongoMapper::Document
  include PageCacheable

  key :filename,     String,   :index => true
  key :contents,     String
  key :processor,    String,   :default => 'plain'
  key :theme_id,     ObjectId, :index => true
  timestamps!
  userstamps!

  # more code here

end
class StylesheetsController < ApplicationController
  caches_page :show

  def show
    render_not_found and return if params[:filename].blank?
    filename = File.basename(params[:filename].first, '.css')

    if stylesheet = Stylesheet.first(:filename => filename,
                                      :theme_id => params[:theme_id])
      if stale?(:etag => stylesheet,
                 :last_modified => stylesheet.updated_at.utc,
                 :public => true)
         render :text => stylesheet.processed_contents, :content_type => 'text/css'
      end
    else
      render_not_found
    end
  end
end
class Asset
  include MongoMapper::Document
  plugin Joint

  def self.versions
     @versions ||= {
       :feature         =>   [:resize,        {:width => 640}],
       :thumb           =>   [:crop_resize,   {:dimensions => [145, 75]}],
       :square          =>   [:crop_resize,   {:dimensions => [75, 75]}],
       :profile         =>   [:crop_resize,   {:dimensions => [100, 100]}],
       :profile_small   =>   [:crop_resize,   {:dimensions => [50, 50]}],
     }
   end

  key :title_tag,       String
  key :description,     String # long description
  timestamps!
  userstamps!

  attachment :file

  # more code here

end
asset = Asset.new
asset.file = params[:uploaded_file]

asset.file.id
asset.file.size
asset.file.type
asset.file.name
class RackAssets
  OriginalRegex = /^/assets/(.*)/(.*)$/        # /assets/:id/name.ext
  VersionRegex = /^/assets/(.*)/(.*)/(.*)$/   # /assets/:id/:version/name.ext

 def initialize(app)
   @app = app
 end

 def call(env)
   case Rack::Request.new(env).path_info
     when VersionRegex
       id, version = $1, $2
       serve_asset(id, version)
     when OriginalRegex
       id = $1
       serve_asset(id)
     else
       @app.call(env)
     end
 end

  def serve_asset(id, version=nil)
    if asset = Asset.find(id)
      asset.page_cache(version)
      [200, {'Content-Type' => asset.file.type}, [File.read(asset.page_cache_path(version))]]
    else
      [404, {'Content-Type' => 'text/plain'}, ['File not found.']]
    end
  end
end
Things to Cover
1. What is Harmony?
2. Multiple Item Types
3. Completely Custom Data
4. Images and Files
5. Activity Streams
6. Wrap Up
Activity Streams
Quick Information
activities   users    items




             assets   themes
activities   users    items




             assets   themes
activities   users    items




             assets   themes
activities   users    items




             assets   themes
class Activity
  include MongoMapper::Document

  key   :user,          Hash
  key   :source,        Hash
  key   :source_type,   String
  key   :action,        String
  key   :count,         Integer, :default => 0

  timestamps!

end
class Activity
  include MongoMapper::Document

  key   :user,          Hash
  key   :source,        Hash
  key   :source_type,   String
  key   :action,        String
  key   :count,         Integer, :default => 0

  timestamps!

  def source=(value)
    if value.is_a?(Hash)
      super
    else
      self.source_type = value.class.name
      super(value.to_mongo)
    end
  end

  def user=(value)
    if value.is_a?(User)
      super :id => value.id, :name => value.full_name
    else
      super
    end
  end

end
class Activity

  # code on previous slide

  def self.article_created(article)
    create(:source => article, :user => article.creator, :action => 'create')
  end

  def self.article_updated(article)
    first_or_new(:action => 'update', :'source._id' => article.id,
                 :created_at.gt => Time.zone.now.beginning_of_day.utc).tap do |a|
      a.count += 1
      a.source = article
      a.user   = article.updater
      a.save
    end
  end

  def self.article_published(article)
    create(:source => article, :user => article.updater, :action => 'publish')
  end

  def self.article_unpublished(article)
    create(:source => article, :user => article.updater, :action => 'unpublish')
  end

end
Things to Cover
1. What is Harmony?
2. Multiple Item Types
3. Completely Custom Data
4. Images and Files
5. Activity Streams
6. Wrap Up
Wrapping Up
Recapping the Main Points
Take advantage of

Dynamic Keys
in Collections
Use Embedding to

Simplify Relationships
Storing Binary Data is

Simple & Useful
Embed Whole Objects for

Archiving and
Query Reduction
Thank you!
steve@orderedlist.com
@orderedlist



MongoSF, San Francisco   Steve Smith
April 30, 2010             Ordered List

More Related Content

What's hot

Storing tree structures with MongoDB
Storing tree structures with MongoDBStoring tree structures with MongoDB
Storing tree structures with MongoDBVyacheslav
 
NoSQL を Ruby で実践するための n 個の方法
NoSQL を Ruby で実践するための n 個の方法NoSQL を Ruby で実践するための n 個の方法
NoSQL を Ruby で実践するための n 個の方法Tomohiro Nishimura
 
Round pegs and square holes
Round pegs and square holesRound pegs and square holes
Round pegs and square holesDaniel Greenfeld
 
Solving the Riddle of Search: Using Sphinx with Rails
Solving the Riddle of Search: Using Sphinx with RailsSolving the Riddle of Search: Using Sphinx with Rails
Solving the Riddle of Search: Using Sphinx with Railsfreelancing_god
 
Intro to MongoDB and datamodeling
Intro to MongoDB and datamodeling Intro to MongoDB and datamodeling
Intro to MongoDB and datamodeling rogerbodamer
 
MongoMapper lightning talk
MongoMapper lightning talkMongoMapper lightning talk
MongoMapper lightning talkKerry Buckley
 
MongoDB, PHP and the cloud - php cloud summit 2011
MongoDB, PHP and the cloud - php cloud summit 2011MongoDB, PHP and the cloud - php cloud summit 2011
MongoDB, PHP and the cloud - php cloud summit 2011Steven Francia
 
Design Summit - Navigating the ManageIQ Object Model - Brad Ascar
Design Summit - Navigating the ManageIQ Object Model - Brad AscarDesign Summit - Navigating the ManageIQ Object Model - Brad Ascar
Design Summit - Navigating the ManageIQ Object Model - Brad AscarManageIQ
 
Indexing & Query Optimization
Indexing & Query OptimizationIndexing & Query Optimization
Indexing & Query OptimizationMongoDB
 
How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!
How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!
How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!Ricardo Signes
 
Webinar: Data Modeling Examples in the Real World
Webinar: Data Modeling Examples in the Real WorldWebinar: Data Modeling Examples in the Real World
Webinar: Data Modeling Examples in the Real WorldMongoDB
 
MTDDC 2010.2.5 Tokyo - Brand new API
MTDDC 2010.2.5 Tokyo - Brand new APIMTDDC 2010.2.5 Tokyo - Brand new API
MTDDC 2010.2.5 Tokyo - Brand new APISix Apart KK
 
MongoDB San Francisco 2013: Data Modeling Examples From the Real World presen...
MongoDB San Francisco 2013: Data Modeling Examples From the Real World presen...MongoDB San Francisco 2013: Data Modeling Examples From the Real World presen...
MongoDB San Francisco 2013: Data Modeling Examples From the Real World presen...MongoDB
 
テスト用のプレゼンテーション
テスト用のプレゼンテーションテスト用のプレゼンテーション
テスト用のプレゼンテーションgooseboi
 
Data Modeling for the Real World
Data Modeling for the Real WorldData Modeling for the Real World
Data Modeling for the Real WorldMike Friedman
 
MongoDB & Mongoid with Rails
MongoDB & Mongoid with RailsMongoDB & Mongoid with Rails
MongoDB & Mongoid with RailsJustin Smestad
 

What's hot (17)

Storing tree structures with MongoDB
Storing tree structures with MongoDBStoring tree structures with MongoDB
Storing tree structures with MongoDB
 
NoSQL を Ruby で実践するための n 個の方法
NoSQL を Ruby で実践するための n 個の方法NoSQL を Ruby で実践するための n 個の方法
NoSQL を Ruby で実践するための n 個の方法
 
Round pegs and square holes
Round pegs and square holesRound pegs and square holes
Round pegs and square holes
 
Solving the Riddle of Search: Using Sphinx with Rails
Solving the Riddle of Search: Using Sphinx with RailsSolving the Riddle of Search: Using Sphinx with Rails
Solving the Riddle of Search: Using Sphinx with Rails
 
Intro to MongoDB and datamodeling
Intro to MongoDB and datamodeling Intro to MongoDB and datamodeling
Intro to MongoDB and datamodeling
 
MongoMapper lightning talk
MongoMapper lightning talkMongoMapper lightning talk
MongoMapper lightning talk
 
MongoDB, PHP and the cloud - php cloud summit 2011
MongoDB, PHP and the cloud - php cloud summit 2011MongoDB, PHP and the cloud - php cloud summit 2011
MongoDB, PHP and the cloud - php cloud summit 2011
 
Design Summit - Navigating the ManageIQ Object Model - Brad Ascar
Design Summit - Navigating the ManageIQ Object Model - Brad AscarDesign Summit - Navigating the ManageIQ Object Model - Brad Ascar
Design Summit - Navigating the ManageIQ Object Model - Brad Ascar
 
Indexing & Query Optimization
Indexing & Query OptimizationIndexing & Query Optimization
Indexing & Query Optimization
 
How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!
How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!
How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!
 
Webinar: Data Modeling Examples in the Real World
Webinar: Data Modeling Examples in the Real WorldWebinar: Data Modeling Examples in the Real World
Webinar: Data Modeling Examples in the Real World
 
MTDDC 2010.2.5 Tokyo - Brand new API
MTDDC 2010.2.5 Tokyo - Brand new APIMTDDC 2010.2.5 Tokyo - Brand new API
MTDDC 2010.2.5 Tokyo - Brand new API
 
Database2
Database2Database2
Database2
 
MongoDB San Francisco 2013: Data Modeling Examples From the Real World presen...
MongoDB San Francisco 2013: Data Modeling Examples From the Real World presen...MongoDB San Francisco 2013: Data Modeling Examples From the Real World presen...
MongoDB San Francisco 2013: Data Modeling Examples From the Real World presen...
 
テスト用のプレゼンテーション
テスト用のプレゼンテーションテスト用のプレゼンテーション
テスト用のプレゼンテーション
 
Data Modeling for the Real World
Data Modeling for the Real WorldData Modeling for the Real World
Data Modeling for the Real World
 
MongoDB & Mongoid with Rails
MongoDB & Mongoid with RailsMongoDB & Mongoid with Rails
MongoDB & Mongoid with Rails
 

Similar to Mongo and Harmony

Ruby Development and MongoMapper (John Nunemaker)
Ruby Development and MongoMapper (John Nunemaker)Ruby Development and MongoMapper (John Nunemaker)
Ruby Development and MongoMapper (John Nunemaker)MongoSF
 
PyCon APAC - Django Test Driven Development
PyCon APAC - Django Test Driven DevelopmentPyCon APAC - Django Test Driven Development
PyCon APAC - Django Test Driven DevelopmentTudor Munteanu
 
Django tech-talk
Django tech-talkDjango tech-talk
Django tech-talkdtdannen
 
Pyconie 2012
Pyconie 2012Pyconie 2012
Pyconie 2012Yaqi Zhao
 
Active Record Form Helpers, Season 1
Active Record Form Helpers, Season 1Active Record Form Helpers, Season 1
Active Record Form Helpers, Season 1RORLAB
 
Test driven development with behat and silex
Test driven development with behat and silexTest driven development with behat and silex
Test driven development with behat and silexDionyshs Tsoumas
 
Django Overview
Django OverviewDjango Overview
Django OverviewBrian Tol
 
Automating Content Import
Automating Content ImportAutomating Content Import
Automating Content ImportDavid Lippman
 
Mongo db Quick Guide
Mongo db Quick GuideMongo db Quick Guide
Mongo db Quick GuideSourabh Sahu
 
APPLICATION TO DOCUMENT ALL THE DETAILS OF JAVA CLASSES OF A PROJECT AT ONCE...
APPLICATION TO DOCUMENT ALL THE  DETAILS OF JAVA CLASSES OF A PROJECT AT ONCE...APPLICATION TO DOCUMENT ALL THE  DETAILS OF JAVA CLASSES OF A PROJECT AT ONCE...
APPLICATION TO DOCUMENT ALL THE DETAILS OF JAVA CLASSES OF A PROJECT AT ONCE...DEEPANSHU GUPTA
 
Cool bonsai cool - an introduction to ElasticSearch
Cool bonsai cool - an introduction to ElasticSearchCool bonsai cool - an introduction to ElasticSearch
Cool bonsai cool - an introduction to ElasticSearchclintongormley
 
Tame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapperTame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapperGiordano Scalzo
 
Building Potent WordPress Websites
Building Potent WordPress WebsitesBuilding Potent WordPress Websites
Building Potent WordPress WebsitesKyle Cearley
 
Intro to Rails ActiveRecord
Intro to Rails ActiveRecordIntro to Rails ActiveRecord
Intro to Rails ActiveRecordMark Menard
 
The Way to Theme Enlightenment 2017
The Way to Theme Enlightenment 2017The Way to Theme Enlightenment 2017
The Way to Theme Enlightenment 2017Amanda Giles
 
Ejb3 Struts Tutorial En
Ejb3 Struts Tutorial EnEjb3 Struts Tutorial En
Ejb3 Struts Tutorial EnAnkur Dongre
 
Ejb3 Struts Tutorial En
Ejb3 Struts Tutorial EnEjb3 Struts Tutorial En
Ejb3 Struts Tutorial EnAnkur Dongre
 
Local data storage for mobile apps
Local data storage for mobile appsLocal data storage for mobile apps
Local data storage for mobile appsIvano Malavolta
 

Similar to Mongo and Harmony (20)

Ruby Development and MongoMapper (John Nunemaker)
Ruby Development and MongoMapper (John Nunemaker)Ruby Development and MongoMapper (John Nunemaker)
Ruby Development and MongoMapper (John Nunemaker)
 
PyCon APAC - Django Test Driven Development
PyCon APAC - Django Test Driven DevelopmentPyCon APAC - Django Test Driven Development
PyCon APAC - Django Test Driven Development
 
68837.ppt
68837.ppt68837.ppt
68837.ppt
 
Django tech-talk
Django tech-talkDjango tech-talk
Django tech-talk
 
Pyconie 2012
Pyconie 2012Pyconie 2012
Pyconie 2012
 
Active Record Form Helpers, Season 1
Active Record Form Helpers, Season 1Active Record Form Helpers, Season 1
Active Record Form Helpers, Season 1
 
Test driven development with behat and silex
Test driven development with behat and silexTest driven development with behat and silex
Test driven development with behat and silex
 
behat
behatbehat
behat
 
Django Overview
Django OverviewDjango Overview
Django Overview
 
Automating Content Import
Automating Content ImportAutomating Content Import
Automating Content Import
 
Mongo db Quick Guide
Mongo db Quick GuideMongo db Quick Guide
Mongo db Quick Guide
 
APPLICATION TO DOCUMENT ALL THE DETAILS OF JAVA CLASSES OF A PROJECT AT ONCE...
APPLICATION TO DOCUMENT ALL THE  DETAILS OF JAVA CLASSES OF A PROJECT AT ONCE...APPLICATION TO DOCUMENT ALL THE  DETAILS OF JAVA CLASSES OF A PROJECT AT ONCE...
APPLICATION TO DOCUMENT ALL THE DETAILS OF JAVA CLASSES OF A PROJECT AT ONCE...
 
Cool bonsai cool - an introduction to ElasticSearch
Cool bonsai cool - an introduction to ElasticSearchCool bonsai cool - an introduction to ElasticSearch
Cool bonsai cool - an introduction to ElasticSearch
 
Tame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapperTame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapper
 
Building Potent WordPress Websites
Building Potent WordPress WebsitesBuilding Potent WordPress Websites
Building Potent WordPress Websites
 
Intro to Rails ActiveRecord
Intro to Rails ActiveRecordIntro to Rails ActiveRecord
Intro to Rails ActiveRecord
 
The Way to Theme Enlightenment 2017
The Way to Theme Enlightenment 2017The Way to Theme Enlightenment 2017
The Way to Theme Enlightenment 2017
 
Ejb3 Struts Tutorial En
Ejb3 Struts Tutorial EnEjb3 Struts Tutorial En
Ejb3 Struts Tutorial En
 
Ejb3 Struts Tutorial En
Ejb3 Struts Tutorial EnEjb3 Struts Tutorial En
Ejb3 Struts Tutorial En
 
Local data storage for mobile apps
Local data storage for mobile appsLocal data storage for mobile apps
Local data storage for mobile apps
 

Mongo and Harmony

  • 1. MongoDB & Harmony Real World Usage of MongoDB MongoSF, San Francisco Steve Smith April 30, 2010 Ordered List
  • 5. Things to Cover 1. What is Harmony? 2. Multiple Item Types 3. Completely Custom Data 4. Images and Files 5. Activity Streams 6. Wrap Up
  • 8. Harmony is design to Be Flexible
  • 9. Harmony is designed to Store Web Content
  • 11. Things to Cover 1. What is Harmony? 2. Multiple Item Types 3. Completely Custom Data 4. Images and Files 5. Activity Streams 6. Wrap Up
  • 16. Harmony has Blog Labels and Archives
  • 20. class Item include MongoMapper::Document key :_type, String, :index => true key :title, String, :required => true key :path, String, :required => true, :index => true key :template_name, String key :published_at, Time key :parent_id, ObjectId, :index => true key :parent_ids, Array, :index => true key :site_id, ObjectId, :required => true, :index => true key :nav_item, Boolean, :default => true key :asset_ids, Array, :index => true timestamps! userstamps! # more code here end
  • 21. class Page < Item key :position, Integer, :default => 1 # more code here end
  • 22. class Blog < Item key :position, Integer, :default => 1 key :labels_as, String, :default => 'tags' key :custom_permalink_structure, String # more code here end
  • 23. class BlogPost < Item key :accepting_comments, Boolean, :default => true key :labels, Set, :index => true key :year_id, ObjectId key :month_id, ObjectId key :day_id, ObjectId # more code here end
  • 24. Separation of Code into Meaningful Keys
  • 26. Things to Cover 1. What is Harmony? 2. Multiple Item Types 3. Completely Custom Data 4. Images and Files 5. Activity Streams 6. Wrap Up
  • 28. Every Item in Harmony gets A Title and a Path
  • 29. All Other Data is Defined by the User
  • 32. templates fields Template 1 Template 2 Template 3
  • 33. templates fields Template 1 Field 1 Field 2 Field 3 Template 2 Field 4 Field 5 Field 6 Template 3 Field 7 Field 8 Field 9
  • 34. This data is not related, it Belongs Together
  • 35. templates Template 1 Field 1 Field 2 Field 3 Template 2 Use Embedded Field 4 Documents Field 5 Field 6 Template 3 Field 7 Field 8 Field 9
  • 36. items
  • 38. items data Item 1 Item 2 Item 3
  • 39. items data Item 1 Data 1 Data 2 Data 3 Item 2 Data 4 Data 5 Data 6 Item 3 Data 7 Data 8 Data 9
  • 40. items templates Item 1 Template 1 Data 1 Field 1 Data 2 Field 2 Data 3 Field 3 Item 2 Template 2 Data 4 Field 4 Data 5 Field 5 Data 6 Field 6 Item 3 Template 3 Data 7 Field 7 Data 8 Field 8 Data 9 Field 9
  • 41. class Template include MongoMapper::Document key :filename, String, :index => true key :theme_id, ObjectId, :index => true key :contents, String timestamps! userstamps! many :fields # more code here end
  • 42. class Field include MongoMapper::EmbeddedDocument key :name, String, :required => true key :key, String, :required => true key :field_type_id, Integer, :required => true key :help_text, String key :settings, Hash key :required, Boolean embedded_in :template # more code here end
  • 43. class Item include MongoMapper::Document key :_type, String, :index => true key :title, String, :required => true key :path, String, :required => true, :index => true key :template_name, String key :published_at, Time key :parent_id, ObjectId, :index => true key :parent_ids, Array, :index => true key :site_id, ObjectId, :required => true, :index => true key :nav_item, Boolean, :default => true key :asset_ids, Array, :index => true timestamps! userstamps! many :data # more code here end
  • 44. class Datum include MongoMapper::EmbeddedDocument key :key, String, :required => true, :length => 2..100 key :file_upload, Boolean, :default => false key :value embedded_in :item # more code here end
  • 47. Things to Cover 1. What is Harmony? 2. Multiple Item Types 3. Completely Custom Data 4. Images and Files 5. Activity Streams 6. Wrap Up
  • 48. Images and Files Binary Data Storage
  • 50. Harmony contains Text Files Stylesheets, JavaScripts, Includes, and Templates
  • 53. class Stylesheet include MongoMapper::Document include PageCacheable key :filename, String, :index => true key :contents, String key :processor, String, :default => 'plain' key :theme_id, ObjectId, :index => true timestamps! userstamps! # more code here end
  • 54. class StylesheetsController < ApplicationController caches_page :show def show render_not_found and return if params[:filename].blank? filename = File.basename(params[:filename].first, '.css') if stylesheet = Stylesheet.first(:filename => filename, :theme_id => params[:theme_id]) if stale?(:etag => stylesheet, :last_modified => stylesheet.updated_at.utc, :public => true) render :text => stylesheet.processed_contents, :content_type => 'text/css' end else render_not_found end end end
  • 55. class Asset include MongoMapper::Document plugin Joint def self.versions @versions ||= { :feature => [:resize, {:width => 640}], :thumb => [:crop_resize, {:dimensions => [145, 75]}], :square => [:crop_resize, {:dimensions => [75, 75]}], :profile => [:crop_resize, {:dimensions => [100, 100]}], :profile_small => [:crop_resize, {:dimensions => [50, 50]}], } end key :title_tag, String key :description, String # long description timestamps! userstamps! attachment :file # more code here end
  • 56. asset = Asset.new asset.file = params[:uploaded_file] asset.file.id asset.file.size asset.file.type asset.file.name
  • 57. class RackAssets OriginalRegex = /^/assets/(.*)/(.*)$/ # /assets/:id/name.ext VersionRegex = /^/assets/(.*)/(.*)/(.*)$/ # /assets/:id/:version/name.ext def initialize(app) @app = app end def call(env) case Rack::Request.new(env).path_info when VersionRegex id, version = $1, $2 serve_asset(id, version) when OriginalRegex id = $1 serve_asset(id) else @app.call(env) end end def serve_asset(id, version=nil) if asset = Asset.find(id) asset.page_cache(version) [200, {'Content-Type' => asset.file.type}, [File.read(asset.page_cache_path(version))]] else [404, {'Content-Type' => 'text/plain'}, ['File not found.']] end end end
  • 58. Things to Cover 1. What is Harmony? 2. Multiple Item Types 3. Completely Custom Data 4. Images and Files 5. Activity Streams 6. Wrap Up
  • 60.
  • 61. activities users items assets themes
  • 62. activities users items assets themes
  • 63. activities users items assets themes
  • 64. activities users items assets themes
  • 65. class Activity include MongoMapper::Document key :user, Hash key :source, Hash key :source_type, String key :action, String key :count, Integer, :default => 0 timestamps! end
  • 66. class Activity include MongoMapper::Document key :user, Hash key :source, Hash key :source_type, String key :action, String key :count, Integer, :default => 0 timestamps! def source=(value) if value.is_a?(Hash) super else self.source_type = value.class.name super(value.to_mongo) end end def user=(value) if value.is_a?(User) super :id => value.id, :name => value.full_name else super end end end
  • 67. class Activity # code on previous slide def self.article_created(article) create(:source => article, :user => article.creator, :action => 'create') end def self.article_updated(article) first_or_new(:action => 'update', :'source._id' => article.id, :created_at.gt => Time.zone.now.beginning_of_day.utc).tap do |a| a.count += 1 a.source = article a.user = article.updater a.save end end def self.article_published(article) create(:source => article, :user => article.updater, :action => 'publish') end def self.article_unpublished(article) create(:source => article, :user => article.updater, :action => 'unpublish') end end
  • 68. Things to Cover 1. What is Harmony? 2. Multiple Item Types 3. Completely Custom Data 4. Images and Files 5. Activity Streams 6. Wrap Up
  • 70. Take advantage of Dynamic Keys in Collections
  • 71. Use Embedding to Simplify Relationships
  • 72. Storing Binary Data is Simple & Useful
  • 73. Embed Whole Objects for Archiving and Query Reduction
  • 74. Thank you! steve@orderedlist.com @orderedlist MongoSF, San Francisco Steve Smith April 30, 2010 Ordered List