2008-12-02 01:20:00 +00:00
|
|
|
= Introduction
|
|
|
|
|
2009-01-07 21:07:22 +00:00
|
|
|
This is a Ruby driver for the 10gen Mongo DB. For more information about
|
|
|
|
Mongo, see http://www.mongodb.org.
|
2008-12-02 01:20:00 +00:00
|
|
|
|
2009-01-07 21:07:22 +00:00
|
|
|
Note: this driver is still alpha quality. The API will change, as *may* the
|
|
|
|
data saved to the database (especially primary key values). Do *_not_* use
|
|
|
|
this for any production data yet.
|
2008-12-04 21:38:04 +00:00
|
|
|
|
2009-01-08 16:48:59 +00:00
|
|
|
Start by reading the XGen::Mongo::Driver::Mongo and XGen::Mongo::Driver::DB
|
|
|
|
documentation, then move on to XGen::Mongo::Driver::Collection and
|
|
|
|
XGen::Mongo::Driver::Cursor.
|
|
|
|
|
|
|
|
A quick code sample:
|
|
|
|
|
|
|
|
require 'mongo'
|
|
|
|
|
|
|
|
include XGen::Mongo::Driver
|
|
|
|
|
|
|
|
db = Mongo.new('localhost').db('sample-db')
|
|
|
|
coll = db.collection('test')
|
|
|
|
|
|
|
|
coll.clear
|
|
|
|
3.times { |i| coll.insert({'a' => i+1}) }
|
|
|
|
puts "There are #{coll.count()} records. Here they are:"
|
|
|
|
coll.find().each { |doc| puts doc.inspect }
|
2008-12-02 01:21:22 +00:00
|
|
|
|
2009-01-29 16:23:50 +00:00
|
|
|
This driver also includes an implementation of a GridStore class, a Ruby
|
|
|
|
interface to Mongo's GridFS storage. NOTE: the GridStore code may be moved to
|
|
|
|
a separate project.
|
|
|
|
|
2009-01-08 16:42:52 +00:00
|
|
|
= Installation
|
|
|
|
|
|
|
|
Install the "mongo" gem by typing
|
|
|
|
|
2009-01-15 21:05:56 +00:00
|
|
|
$ gem sources -a http://gems.github.com
|
2009-01-15 21:49:01 +00:00
|
|
|
$ sudo gem install mongodb-mongo-ruby-driver
|
2009-01-08 16:42:52 +00:00
|
|
|
|
2009-01-23 13:53:48 +00:00
|
|
|
The first line tells RubyGems to add the GitHub gem repository. You only need
|
|
|
|
to run this command once.
|
|
|
|
|
|
|
|
=== From the GitHub source
|
|
|
|
|
2009-01-15 21:05:56 +00:00
|
|
|
The source code is available at http://github.com/mongodb/mongo-ruby-driver.
|
|
|
|
You can either clone the git repository or download a tarball or zip file.
|
|
|
|
Once you have the source, you can use it from wherever you downloaded it or
|
|
|
|
you can install it as a gem from the source by typing
|
2009-01-08 16:42:52 +00:00
|
|
|
|
|
|
|
$ rake gem:install
|
|
|
|
|
|
|
|
|
2008-12-02 01:20:00 +00:00
|
|
|
= Demo
|
|
|
|
|
2009-01-08 16:42:52 +00:00
|
|
|
You can see and run the examples if you've downloaded the source. Mongo must
|
|
|
|
be running, of course.
|
2009-01-07 21:07:22 +00:00
|
|
|
|
2008-12-17 16:43:08 +00:00
|
|
|
$ ruby examples/simple.rb
|
2008-12-02 01:20:00 +00:00
|
|
|
|
2009-01-08 16:42:52 +00:00
|
|
|
See also the test code, especially tests/test_db_api.rb.
|
2008-12-02 01:20:00 +00:00
|
|
|
|
2009-01-29 16:23:50 +00:00
|
|
|
For the GridFS class GridStore, see the tests.
|
|
|
|
|
|
|
|
|
2009-01-29 16:31:45 +00:00
|
|
|
= The Driver
|
|
|
|
|
|
|
|
Here is some simple example code:
|
|
|
|
|
|
|
|
require 'rubygems' # not required for Ruby 1.9
|
|
|
|
require 'mongo'
|
|
|
|
|
|
|
|
include XGen::Mongo::Driver
|
|
|
|
db = Mongo.new.db('my-db-name')
|
|
|
|
things = db.collection('things')
|
|
|
|
|
|
|
|
things.clear
|
|
|
|
things.insert('a' => 42)
|
|
|
|
things.insert('a' => 99, 'b' => Time.now)
|
|
|
|
puts things.count # => 2
|
|
|
|
puts things.find('a' => 42).next_object.inspect # {"a"=>42}
|
|
|
|
|
|
|
|
|
2009-01-29 16:23:50 +00:00
|
|
|
= GridStore
|
|
|
|
|
|
|
|
The GridStore class is a Ruby implementation of Mongo's GridFS file storage
|
|
|
|
system. An instance of GridStore is like an IO object. See the rdocs for
|
|
|
|
details.
|
|
|
|
|
2009-01-29 16:31:45 +00:00
|
|
|
Note that the GridStore class is not automatically required when you require
|
|
|
|
'mongo'. You need to require 'mongo/gridfs'.
|
|
|
|
|
|
|
|
Example code:
|
|
|
|
|
|
|
|
GridStore.open(database, 'filename', 'w') { |f|
|
|
|
|
f.puts "Hello, world!"
|
|
|
|
}
|
|
|
|
GridStore.open(database, 'filename, 'r') { |f|
|
|
|
|
puts f.read # => Hello, world!\n
|
|
|
|
}
|
|
|
|
GridStore.open(database, 'filename', 'w+') { |f|
|
|
|
|
f.puts "But wait, there's more!"
|
|
|
|
}
|
|
|
|
GridStore.open(database, 'filename, 'r') { |f|
|
|
|
|
puts f.read # => Hello, world!\nBut wait, there's more!\n
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-02 01:21:22 +00:00
|
|
|
|
2009-01-13 17:53:55 +00:00
|
|
|
= Notes
|
|
|
|
|
|
|
|
== String Encoding
|
|
|
|
|
|
|
|
The BSON ("Binary JSON") format used to communicate with Mongo requires that
|
|
|
|
strings be UTF-8 (http://en.wikipedia.org/wiki/UTF-8).
|
|
|
|
|
|
|
|
Ruby 1.9 has built-in character encoding support. All strings sent to Mongo
|
|
|
|
and received from Mongo are converted to UTF-8 when necessary, and strings
|
|
|
|
read from Mongo will have their character encodings set to UTF-8.
|
|
|
|
|
|
|
|
When used with Ruby 1.8, the bytes in each string are written to and read from
|
|
|
|
Mongo as-is. If the string is ASCII all is well, because ASCII is a subset of
|
2009-01-16 19:41:53 +00:00
|
|
|
UTF-8. If the string is not ASCII then it may not be a well-formed UTF-8
|
|
|
|
string.
|
|
|
|
|
2009-02-01 14:14:21 +00:00
|
|
|
== Primary Keys
|
|
|
|
|
|
|
|
The field _id is a primary key. It is treated specially by the database, and
|
|
|
|
its use makes many operations more efficient.
|
|
|
|
|
|
|
|
The value of an _id may be of any type. (Older versions of Mongo required that
|
|
|
|
they be XGen::Mongo::Driver::ObjectID instances.)
|
|
|
|
|
|
|
|
The database itself inserts an _id value if none is specified when a record is
|
|
|
|
inserted.
|
2009-01-16 19:41:53 +00:00
|
|
|
|
|
|
|
=== Primary Key Factories
|
|
|
|
|
2009-02-01 14:14:21 +00:00
|
|
|
A primary key factory is a class you supply to a DB object that knows how to
|
|
|
|
generate _id values. Primary key factories are no longer necessary because
|
|
|
|
Mongo now inserts an _id value for every record that does not already have
|
|
|
|
one. However, if you want to control _id values or even their types, using a
|
|
|
|
PK factory lets you do so.
|
|
|
|
|
|
|
|
You can tell the Ruby Mongo driver how to create primary keys by passing in
|
|
|
|
the :pk option to the Mongo#db method.
|
2009-01-16 19:41:53 +00:00
|
|
|
|
|
|
|
include XGen::Mongo::Driver
|
2009-01-16 21:13:54 +00:00
|
|
|
db = Mongo.new.db('dbname', :pk => MyPKFactory.new)
|
2009-01-16 19:41:53 +00:00
|
|
|
|
|
|
|
A primary key factory object must respond to :create_pk, which should take a
|
|
|
|
hash and return a hash which merges the original hash with any primary key
|
|
|
|
fields the factory wishes to inject. NOTE: if the object already has a primary
|
|
|
|
key, the factory should not inject a new key; this means that the object is
|
|
|
|
being used in a repsert but it already exists. The idea here is that when ever
|
|
|
|
a record is inserted, the :pk object's +create_pk+ method will be called and
|
|
|
|
the new hash returned will be inserted.
|
|
|
|
|
|
|
|
Here is a sample primary key factory, taken from the tests:
|
|
|
|
|
|
|
|
class TestPKFactory
|
|
|
|
def create_pk(row)
|
|
|
|
row['_id'] ||= XGen::Mongo::Driver::ObjectID.new
|
|
|
|
row
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-01-29 16:31:45 +00:00
|
|
|
Here's a slightly more sophisticated one that handles both symbol and string
|
|
|
|
keys. This is the PKFactory that comes with the MongoRecord code (an
|
|
|
|
ActiveRecord-like framework for non-Rails apps) and the AR Mongo adapter code
|
|
|
|
(for Rails):
|
|
|
|
|
|
|
|
class PKFactory
|
|
|
|
def create_pk(row)
|
|
|
|
return row if row[:_id]
|
|
|
|
row.delete(:_id) # in case it exists but the value is nil
|
|
|
|
row['_id'] ||= XGen::Mongo::Driver::ObjectID.new
|
|
|
|
row
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-02-01 14:14:21 +00:00
|
|
|
A database's PK factory object may be set either when a DB object is created
|
|
|
|
or immediately after you obtain it, but only once. The only reason it is
|
|
|
|
changeable at all is so that libraries such as MongoRecord that use this
|
|
|
|
driver can set the PK factory after obtaining the database but before using it
|
|
|
|
for the first time.
|
|
|
|
|
|
|
|
== The DB Class
|
|
|
|
|
|
|
|
=== Primary Key factories
|
|
|
|
|
|
|
|
See the section on "Primary Keys" above.
|
2009-01-16 19:41:53 +00:00
|
|
|
|
|
|
|
=== Strict mode
|
|
|
|
|
|
|
|
Each database has an optional strict mode. If strict mode is on, then asking
|
|
|
|
for a collection that does not exist will raise an error, as will asking to
|
|
|
|
create a collection that already exists. Note that both these operations are
|
|
|
|
completely harmless; strict mode is a programmer convenience only.
|
|
|
|
|
|
|
|
To turn on strict mode, either pass in :strict => true when obtaining a DB
|
|
|
|
object or call the :strict= method:
|
|
|
|
|
|
|
|
db = XGen::Mongo::Driver::Mongo.new.db('dbname', :strict => true)
|
|
|
|
# I'm feeling lax
|
|
|
|
db.strict = false
|
|
|
|
# No, I'm not!
|
|
|
|
db.strict = true
|
|
|
|
|
|
|
|
The method DB#strict? returns the current value of that flag.
|
|
|
|
|
2009-01-13 17:53:55 +00:00
|
|
|
|
2008-12-02 01:20:00 +00:00
|
|
|
= Testing
|
|
|
|
|
2009-01-08 16:42:52 +00:00
|
|
|
If you have the source code, you can run the tests.
|
|
|
|
|
2008-12-02 01:20:00 +00:00
|
|
|
$ rake test
|
|
|
|
|
2009-01-29 15:42:20 +00:00
|
|
|
The tests assume that the Mongo database is running on the default port. You
|
|
|
|
can override the default host (localhost) and port (Mongo::DEFAULT_PORT) by
|
|
|
|
using the environment variables MONGO_RUBY_DRIVER_HOST and
|
|
|
|
MONGO_RUBY_DRIVER_PORT.
|
2008-12-02 01:20:00 +00:00
|
|
|
|
2009-01-12 14:48:24 +00:00
|
|
|
The project mongo-qa (http://github.com/mongodb/mongo-qa) contains many more
|
|
|
|
Mongo driver tests that are language independent. To run thoses tests as part
|
2009-01-28 19:15:21 +00:00
|
|
|
of the "rake test" task, download the code "next to" this directory. So, after
|
|
|
|
installing the mongo-qa code you would have these two directories next to each
|
|
|
|
other:
|
2009-01-12 14:48:24 +00:00
|
|
|
|
2009-01-28 19:15:21 +00:00
|
|
|
$ ls
|
|
|
|
mongo-qa
|
|
|
|
mongo-ruby-driver
|
2009-01-12 14:48:24 +00:00
|
|
|
$ rake test
|
|
|
|
|
2009-01-28 19:15:21 +00:00
|
|
|
The tests run just fine if the mongo-qa directory is not there.
|
2009-01-12 14:48:24 +00:00
|
|
|
|
2009-01-12 16:23:07 +00:00
|
|
|
Additionally, the script bin/validate is used by the mongo-qa project's
|
|
|
|
validator script.
|
|
|
|
|
2008-12-02 01:21:22 +00:00
|
|
|
|
2008-12-04 22:02:19 +00:00
|
|
|
= Documentation
|
|
|
|
|
2009-01-08 16:42:52 +00:00
|
|
|
This documentation is available online at http://mongo.rubyforge.org. You can
|
|
|
|
generate the documentation if you have the source by typing
|
|
|
|
|
2008-12-04 22:02:19 +00:00
|
|
|
$ rake rdoc
|
|
|
|
|
2009-01-08 16:42:52 +00:00
|
|
|
Then open the file html/index.html.
|
2008-12-02 15:45:02 +00:00
|
|
|
|
|
|
|
|
2009-01-07 21:07:22 +00:00
|
|
|
= Release Notes
|
2008-12-02 15:45:02 +00:00
|
|
|
|
2009-01-07 17:51:16 +00:00
|
|
|
See the git log comments.
|
2008-12-02 15:45:02 +00:00
|
|
|
|
|
|
|
|
2008-12-02 01:21:22 +00:00
|
|
|
= To Do
|
|
|
|
|
2009-01-07 21:56:34 +00:00
|
|
|
* Add group_by. Need to figure out how we are going to send functions. The
|
|
|
|
current thinking is that Mongo will allow a subset of JavaScript (which we
|
|
|
|
would have to send as a string), but this is still under discussion.
|
|
|
|
|
2008-12-17 16:03:09 +00:00
|
|
|
* Tests for update and repsert.
|
|
|
|
|
2008-12-16 22:35:31 +00:00
|
|
|
* Add a way to specify a collection of databases on startup (a simple array of
|
|
|
|
IP address/port numbers, perhaps, or a hash or something). The driver would
|
2008-12-16 22:19:53 +00:00
|
|
|
then find the master and, on each subsequent command, ask that machine if it
|
|
|
|
is the master before proceeding.
|
2008-12-16 22:08:15 +00:00
|
|
|
|
2008-12-04 21:25:51 +00:00
|
|
|
* Introduce optional per-database and per-collection PKInjector.
|
|
|
|
|
2008-12-02 01:21:22 +00:00
|
|
|
* More tests.
|
|
|
|
|
2009-01-14 15:45:12 +00:00
|
|
|
== Optimizations
|
|
|
|
|
|
|
|
* Only update message sizes once, not after every write of a value. This will
|
|
|
|
require an explicit call to update_message_length in each message subclass.
|
|
|
|
|
|
|
|
* ensure_index commands should be cached to prevent excessive communication
|
|
|
|
with the database. (Or, the driver user should be informed that ensure_index
|
|
|
|
is not a lightweight operation for the particular driver.)
|
2008-12-02 12:22:32 +00:00
|
|
|
|
2008-12-02 01:21:22 +00:00
|
|
|
|
2008-12-05 21:39:00 +00:00
|
|
|
= Credits
|
|
|
|
|
|
|
|
Adrian Madrid, aemadrid@gmail.com
|
2009-01-06 15:49:18 +00:00
|
|
|
* bin/mongo_console
|
2008-12-05 21:39:00 +00:00
|
|
|
* examples/benchmarks.rb
|
|
|
|
* examples/irb.rb
|
2008-12-08 20:08:14 +00:00
|
|
|
* Modifications to examples/simple.rb
|
|
|
|
* Found plenty of bugs and missing features.
|
2009-01-06 15:49:18 +00:00
|
|
|
* Ruby 1.9 support.
|
|
|
|
* Gem support.
|
2008-12-08 20:08:14 +00:00
|
|
|
* Many other code suggestions and improvements.
|
2008-12-05 21:39:00 +00:00
|
|
|
|
|
|
|
|
2008-12-02 01:20:00 +00:00
|
|
|
= License
|
|
|
|
|
2009-01-06 15:51:01 +00:00
|
|
|
Copyright (C) 2008-2009 10gen Inc.
|
2008-12-02 01:20:00 +00:00
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify it under
|
|
|
|
the terms of the GNU Affero General Public License, version 3, as published by
|
|
|
|
the Free Software Foundation.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
|
|
details.
|
|
|
|
|
2008-12-17 16:49:06 +00:00
|
|
|
See http://www.gnu.org/licenses for a copy of the GNU Affero General Public
|
2008-12-02 01:20:00 +00:00
|
|
|
License.
|