SlideShare a Scribd company logo
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
Mongo and Harmony
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

KEY
Elastic tire demo
PDF
10gen Presents Schema Design and Data Modeling
PPTX
Advanced Document Modeling Techniques from a High-Scale Commerce Platform
PPT
Schema design short
PDF
Write better python code with these 10 tricks | by yong cui, ph.d. | aug, 202...
PDF
Solr's Search Relevancy (Understand Solr's query debug)
PDF
Improving RDF Search Performance with Lucene and SIREN
KEY
Schema Design with MongoDB
Elastic tire demo
10gen Presents Schema Design and Data Modeling
Advanced Document Modeling Techniques from a High-Scale Commerce Platform
Schema design short
Write better python code with these 10 tricks | by yong cui, ph.d. | aug, 202...
Solr's Search Relevancy (Understand Solr's query debug)
Improving RDF Search Performance with Lucene and SIREN
Schema Design with MongoDB

What's hot (17)

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

Similar to Mongo and Harmony (20)

PDF
Ruby Development and MongoMapper (John Nunemaker)
PPTX
PyCon APAC - Django Test Driven Development
PPT
68837.ppt
ODP
Django tech-talk
PDF
Pyconie 2012
KEY
Active Record Form Helpers, Season 1
PDF
Test driven development with behat and silex
PDF
Django Overview
PPTX
Automating Content Import
PPTX
Mongo db Quick Guide
PPT
WEB DESIGNING VNSGU UNIT 4 JAVASCRIPT OBJECTS
PDF
APPLICATION TO DOCUMENT ALL THE DETAILS OF JAVA CLASSES OF A PROJECT AT ONCE...
ODP
Cool bonsai cool - an introduction to ElasticSearch
PDF
Tame Accidental Complexity with Ruby and MongoMapper
PPTX
Building Potent WordPress Websites
PPT
Intro to Rails ActiveRecord
PPTX
The Way to Theme Enlightenment 2017
PDF
Ejb3 Struts Tutorial En
PDF
Ejb3 Struts Tutorial En
Ruby Development and MongoMapper (John Nunemaker)
PyCon APAC - Django Test Driven Development
68837.ppt
Django tech-talk
Pyconie 2012
Active Record Form Helpers, Season 1
Test driven development with behat and silex
Django Overview
Automating Content Import
Mongo db Quick Guide
WEB DESIGNING VNSGU UNIT 4 JAVASCRIPT OBJECTS
APPLICATION TO DOCUMENT ALL THE DETAILS OF JAVA CLASSES OF A PROJECT AT ONCE...
Cool bonsai cool - an introduction to ElasticSearch
Tame Accidental Complexity with Ruby and MongoMapper
Building Potent WordPress Websites
Intro to Rails ActiveRecord
The Way to Theme Enlightenment 2017
Ejb3 Struts Tutorial En
Ejb3 Struts Tutorial En
Ad

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
  • 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