Using Mongomapper to store dynamic data

6,480 views

Published on

Introduction to mongodb and mongomapper, and an example of using a schemaless storage system to store dynamic data.

This was given at Fosdem 2010 in the Ruby devroom

Published in: Technology, Business

Using Mongomapper to store dynamic data

  1. 1. MONGODB AND RUBY Persisting dynamic data with MongoMapper
  2. 2. MONGODB • humongous • auto-sharding • Speed!!! • replication and fail-over • document-oriented storage • GridFS (BSON) • MapReduce • dynamic queries • Schemaless • fast, in-place updates
  3. 3. USE IT FOR.. • (most) Websites • Caching • Scalabilty
  4. 4. SKIP IT FOR.. • Transactions • Lots of joins • Fixed datasets (science,...)
  5. 5. START USING IT • MongoDB in google: www.mongodb.org - Quickstart • make a directory • download mongodb • unpack
  6. 6. START USING IT
  7. 7. START USING IT
  8. 8. QUERYING > db.fosdem.save({talk: "MongoDB", presenter: "Bernard"}) > db.fosdem.find() { "_id" : ObjectId("4b681a1ecf1bcfea49f4b2ae"), "talk" : "MongoDB", "presenter" : "Bernard" }
  9. 9. MORE QUERYING > db.fosdem.find({presenter: "Bernard") { "_id" : ObjectId("4b681a1ecf1bcfea49f4b2ae"), "talk" : "MongoDB", "presenter" : "Bernard" }
  10. 10. MORE QUERYING
  11. 11. gem install mongo_mapper gem install mongo_ext
  12. 12. require 'mongo_mapper' MongoMapper.database = ‘fosdem’
  13. 13. class Presenter include MongoMapper::Document end
  14. 14. class Presenter include MongoMapper::Document key :name, String key :confirmed, Boolean key :keywords, Array key :presentation, Presentation end
  15. 15. presenter = Presenter.new({ :name => “Bernard”, :confirmed => true, :keywords => [“Openminds”, “geek”] }) presenter.save presenter.destroy
  16. 16. ACTIVERECORD, ANYONE?
  17. 17. MONGOMAPPER HAS • validates_* • before_save / after_update / ... • has_many / belongs_to • timestamps!
  18. 18. CUSTOM DATATYPES class Keywords class Presenter def initialize(array) include MongoMapper::Document @words = array key :keywords, Keywords end end def to_a @words end class << self def to_mongo(value) value.is_a?(Keyword) ? keyword.to_a : value end def from_mongo(value) value ? self.new(value) : nil end end end
  19. 19. EMBEDDED DOCUMENT include MongoMapper::EmbeddedDocument
  20. 20. DYNAMIC?
  21. 21. INHERITANCE class Page class BlogPost < Page key :permalink, String key :content, String key :title, String has_many :comments end end class Redirect < Page key :destination, String end
  22. 22. MODULAR module Authentication def self.included(base) base.key :password, String base.key :salt, String base.key :login, String end end class Person include MongoMapper::Document include Authentication end
  23. 23. MULTISITE WEBSHOP EXAMPLE per instance data gathering
  24. 24. ORDERS AS A DOCUMENT class Order include MongoMapper::Document key :order_id, String class << self def for_site(site) klass = Class.new(self) klass.order_fields = site.order_fields Object.const_set("OrderForSite#{site.id}", klass) klass end def order_fields=(fields) fields.each do |field| key field, String end end end end
  25. 25. ORDERS: MONGOMAPPER class Order include MongoMapper::Document key :order_id, String
  26. 26. ORDER: CLASS FOR A SPECIFIC SITE def for_site(site) klass = Class.new(self) klass.order_fields = site.order_fields Object.const_set("OrderForSite#{site.id}", klass) klass end
  27. 27. DYNAMIC DOCUMENT BUILDING def order_fields=(fields) fields.each do |field| key field, String end end
  28. 28. PER USER class Order include MongoMapper::Document key :order_id, String class << self def for_site(site) klass = Class.new(self) klass.order_fields = site.order_fields Object.const_set("OrderForSite#{site.id}", klass) klass end def order_fields=(fields) fields.each do |field| key field, String end end end end
  29. 29. SITE • Can be a Mongo-document • Can be an ActiveRecord object • Can be a (Rails 3) ActiveModel object (REST?) • Has to “respond_to? :id” and “respond_to? :order_fields”
  30. 30. TRY IT OUT current_site.order_fields #=> [“field1”, “field2”] @order = Order.for_site(current_site).new #=> #<OrderForSite2172858380 field1: nil, field2: nil, order_id: nil>
  31. 31. Q&A
  32. 32. 1 2 3 4 5 6 7 • Bernard Grymonpon 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 • Openminds BVBA • Hosting & Rails-shop ribbit • @wonko_be - @openminds_be Top sites deserve maximum uptime openminds.be tailored hosting solutions

×