Your SlideShare is downloading. ×
Mysql to mongo
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Mysql to mongo

6,290
views

Published on

Slides for Presentation given at MongoLA on January 13, 2011 at Media Temple.

Slides for Presentation given at MongoLA on January 13, 2011 at Media Temple.

Published in: Technology

0 Comments
5 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
6,290
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
54
Comments
0
Likes
5
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. MYSQL TO MONGO (FTW) Thinking Differently About Schema Design
  • 2. @AJSHARP Alex Sharp Lead Developer, OptimisCorp alexjsharp.com github.com/ajsharp
  • 3. CVBEAST Mongo has many cool features such as schema- free, aggregation w map/reduce and many others Side project interested more in domain modeling more than performance and scaling benefits of Mongo EMBEDDED OBJECTS
  • 4. CVBEAST App to represent people’s curriculum vitae, but not in an academic sense
  • 5. CVBEAST Focus on “micro” experiences not suitable for a typical CV (definitely not suitable for a resumé)
  • 6. CVBEAST Simple object model, centered around highlighting attributes of a person
  • 7. CVBEAST Started out building with MySQL, b/c it’s familiar
  • 8. OBJECT MODEL Person has a CV has many Experience has many ... ... ...
  • 9. OBJECT MODEL Person has a CV links, tags, and has many other arbitrary properties Experience has many ... ... ...
  • 10. RELATIONAL SCHEMA people - id - name - ... cvs - id - person_id - ... experiences - id - cv_id - ...
  • 11. RELATIONAL SCHEMA Lots of pointless JOINs
  • 12. RELATIONAL SCHEMA people - id - name - ... cvs - id - person_id - ... experiences - id - cv_id - ...
  • 13. RELATIONAL SCHEMA people - id - name - ... cvs tags - id - id - name - person_id - ... - ... links experiences - id - name - id - ... - cv_id - ...
  • 14. not b/c of premature optimization this bothers me
  • 15. It misrepresents the object model at the storage layer
  • 16. It also became difficult to work with despite my familiarity with MySQL
  • 17. It makes sense to store object relationships in first-class entities/documents/tables
  • 18. But true object properties should be stored as properties
  • 19. Not relationships.
  • 20. Especially when properties have no practical meaning without the parent
  • 21. CAVEAT This is not always the case. ;-) if you need to: * store LOTS of embedded objects (i.e. papermill)
  • 22. EXAMPLE Experience Links
  • 23. EXPERIENCE.LINKS = [...] Dead-simple collection of links attached to an experience
  • 24. RUBY MODEL CODE class Person include Mongoid::Document field :keywords, :type => Array index :keywords index 'cv.experiences.tags' end
  • 25. class Experience include Mongoid::Document embeds_many :links end class Link include Mongoid::Document field :url field :title embedded_in :experience, :inverse_of => :links end
  • 26. class Experience include Mongoid::Document embeds_many :links end Both models are embedded in the person collection class Link include Mongoid::Document field :url field :title embedded_in :experience, :inverse_of => :links end
  • 27. EXPERIENCE.LINKS = [...] A link is only relevant inside the context of an experience object.
  • 28. EXPERIENCE.LINKS = [...] In other words, it is a property, not a relationship.
  • 29. EXPERIENCE.LINKS = [...] Mongo brings the storage layer closer to the object model
  • 30. EXPERIENCE.LINKS = [...] { "title": "Presented at MongoLA", "links": [ { "title": "Event Site", "url": "http://www.10gen.com/conferences/mongola2011"}, { "title": "Slides", "url": "http://alexjsharp.com/posts/mongola-2010-slides"} ] }
  • 31. EXAMPLE Embedded Search
  • 32. MYSQL An exercise in masochism
  • 33. The difficulty in MySQL came in working with properties of a person
  • 34. These properties are represented as tables
  • 35. And tables must be joined
  • 36. SIMPLE SEARCH QUERY select * from people inner join cvs on cvs.person_id = people.id inner join experiences on experiences.cv_id = cvs.id inner join tags on tags.experience_id = experiences.id where tags.name = 'ruby';
  • 37. INDEXES NEEDED - tags.experience_id - tags.name - experiences.cv_id - cvs.person_id
  • 38. Seems extremely unnecessary for such a simple object model
  • 39. MONGO An exercise in ... not masochism
  • 40. Embedded objects make this query easy.
  • 41. MONGO DOCUMENT “SCHEMA” {"name": "Alex Sharp", "cv": { "experiences": [ { "title": "spoke at MongoLA", "date" : "Thu Jan 13 2011", "tags" : ["mongodb", "speaking"] }, {"title": "..."} ] } }
  • 42. MONGO DOCUMENT “SCHEMA” {"name": "Alex Sharp", "cv": { "experiences": [ { "title": "spoke at MongoLA", "date" : "Thu Jan 13 2011", "tags" : ["mongodb", "speaking"] }, {"title": "..."} ] } } we want to search for these
  • 43. RUBY MODEL CODE class Person include Mongoid::Document field :keywords, :type => Array index :keywords index 'cv.experiences.tags' end
  • 44. RUBY MODEL CODE class Cv include Mongoid::Document embeds_many :experiences end class Experience include Mongoid::Document field :tags, :type => Array, :default => [] embedded_in :cv, :inverse_of => :experiences embeds_many :links after_save lambda { |exp| exp.cv.person.update_keywords } end
  • 45. RUBY MODEL CODE class Cv include Mongoid::Document simple property embeds_many :experiences end (not relationship) class Experience include Mongoid::Document field :tags, :type => Array, :default => [] embedded_in :cv, :inverse_of => :experiences embeds_many :links after_save lambda { |exp| exp.cv.person.update_keywords } end
  • 46. RUBY SEARCH CODE class Person # i.e. db.people.find({"cv.experiences.tags": "ruby"}) def self.search_by_tag(term) collection.find('cv.experiences.tags' => 'ruby') end end
  • 47. COMPARISON select * from people inner join cvs on cvs.person_id = people.id inner join experiences on experiences.cv_id = cvs.id inner join tags on tags.experience_id = experiences.id where tags.name = 'ruby'; vs db.people.find('cv.experiences.tags' => 'ruby')
  • 48. WINS: IMPEDENCE MIS-MATCH Object persistence format is closer to application usage format
  • 49. WINS: F(X)-ALITY Plus, we don’t lose any functionality.
  • 50. WINS: FAMILIARITY Indexing principles are extremely familiar to relational database users.
  • 51. WINS: FAMILIARITY Only simpler ;)
  • 52. WINS: SIMPLICITY Query syntax is simple.
  • 53. WINS: SIMPLICITY Dot notation > JOIN semantics filth
  • 54. SUMMARY Mongo is perfectly suited for an app like CVBeast.
  • 55. SUMMARY Where a relational DB forces storing object properties as relationships
  • 56. SUMMARY Mongo narrows this mismatch considerably
  • 57. SUMMARY A CV is a document...
  • 58. SUMMARY So a document-oriented datastore seems appropriate.
  • 59. SUMMARY Many object models have this tree-like structure.
  • 60. SUMMARY Be willing to step outside of your comfort zone
  • 61. SUMMARY And use Mongo when it’s practical.