Upgrade to Pro — share decks privately, control downloads, hide ads and more …

MongoDB on Rails

Dan Adams
December 14, 2011

MongoDB on Rails

Intro to MongoDB including document insert and updating, MapReduce, and querying. MongoMapper, Mongoid, and the Ruby driver. Testing with Mongoid.

Dan Adams

December 14, 2011
Tweet

Other Decks in Programming

Transcript

  1. WHAT IS MONGODB? Document-oriented NoSQL database Documents are JSON (or

    BSON). API is JS. Querying • Dynamic querying using expressions or JS • Server-side queries and MapReduce • Upserts and in-place updates including incr / decr, data structure operations, and embedded docs Master-slave replication, replica sets, auto-sharding GridFS for binary storage 2
  2. GETTING STARTED Install Start the server Run console Create collection

    Have at it! 3 $ brew update $ brew install mongodb $ sudo mongod & $ mongo > use mongo_talk > db.posts.save({ "title": "MongoDB rocks", "awesome": true, "author_names": ["Steve", "Aaron"], "sub_document": { "foo": "bar", "bar": "baz" } }) > db.posts.find() { "_id" : ObjectId("4edd0daaf3f4ea2b13635930"), "title" : "MongoDB rocks", "awesome" : true, "author_names" : [ "Steve", "Aaron" ], "sub_document" : { "foo" : "bar", "bar" : "baz" } }
  3. INSERTS AND UPDATES db.collection.insert(doc) : inserts a new document db.collection.save(doc)

    : upsert a doc db.collection.update(criteria, obj, upsert, multi) • Single document replacement and upsert • In-place updates (one or more documents) 4
  4. QUERYING find() aggregates: count, distinct, group eval() : arbitrary server-side

    JS 5 > db.posts.find({ "vote_count": {$gt: 50} }) .sort({ "vote_count": -1 }) .skip(10) .limit(10) > db.posts.find({ title: /post 9.*/}) > db.posts.find({ $where: "this.vote_count % 2 == 0" })
  5. MAPREDUCE 6 > m = function() { emit(this.vote_count % 2,

    { count: 1 }); } > r = function (k, values) { var total = 0; for (var i = 0; i < values.length; i++) { total += values[i].count; } return {count:total}; } > res = db.posts.mapReduce(m, r, { out: "post_vote_counts" }) { "result" : "post_vote_counts", "timeMillis" : 5, "counts" : { "input" : 102, "emit" : 102, "output" : 3 }, "ok" : 1, } > db.post_vote_counts.find() { "_id" : 0, "value" : { "count" : 50 } } { "_id" : 1, "value" : { "count" : 51 } } >
  6. INDEXES db.collection.ensureIndex({someprop: 1}) Options • Direction: 1 (ascending), -1 (descending)

    • Multi-field • Background • Unique • Sparse _id index created automatically 7
  7. RUBY DRIVER 8 $ gem install mongo bson bson_ext require

    'mongo' db = Mongo::Connection.new('localhost').db('mongo_talk') coll = db["posts"] coll.save({ title: 'A nice post about Ruby', popular: true }) coll.find( :vote_count => { :$gt => 5 }).each { |post| puts post["title"] }
  8. MONGOMAPPER 9 class User include MongoMapper::Document key :name, String key

    :age, Integer many :hobbies end class Hobby include MongoMapper::EmbeddedDocument key :name, String key :started, Time end $ gem install mongo_mapper user = User.new(:name => 'Brandon') user.hobbies.build(:name => 'Programming', :started => 10.years.ago) user.save! User.where(:name => 'Brandon').first
  9. MONGOID 10 gem "mongoid", "~> 2.3" gem "bson_ext", "~> 1.4"

    class Person include Mongoid::Document field :first_name, type: String field :middle_name, type: String field :last_name, type: String end Person.create!(first_name: "Heinrich", last_name: "Heine") Person.where(first_name: "Emmanuel").asc(:first_name).skip(20).limit(10) Person.all(conditions: { title: "Sir" }, limit: 5, sort: [[ :first_name, :asc ]])
  10. WHICH ONE? Ruby driver: easy to use, no Rails, feels

    like the console MongoMapper • Built on plugins • Better relational support Mongoid • Saves only changed properties using update() • Supports Master / slave replication • DSL for dynamic querying. Feels like the console. • Better docs, more active community • Seems to have gained real momentum Both look pretty great (I’ve been using Mongoid) 11