mongo 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,134 @@
1
+ = Introduction
2
+
3
+ This is a Ruby driver for the 10gen Mongo DB. For more information about
4
+ Mongo, see http://www.mongodb.org.
5
+
6
+ Note: this driver is still alpha quality. The API will change, as *may* the
7
+ data saved to the database (especially primary key values). Do *_not_* use
8
+ this for any production data yet.
9
+
10
+ Start by reading the XGen::Mongo::Driver::Mongo and XGen::Mongo::Driver::DB
11
+ documentation, then move on to XGen::Mongo::Driver::Collection and
12
+ XGen::Mongo::Driver::Cursor.
13
+
14
+ A quick code sample:
15
+
16
+ require 'mongo'
17
+
18
+ include XGen::Mongo::Driver
19
+
20
+ db = Mongo.new('localhost').db('sample-db')
21
+ coll = db.collection('test')
22
+
23
+ coll.clear
24
+ 3.times { |i| coll.insert({'a' => i+1}) }
25
+ puts "There are #{coll.count()} records. Here they are:"
26
+ coll.find().each { |doc| puts doc.inspect }
27
+
28
+ = Installation
29
+
30
+ Install the "mongo" gem by typing
31
+
32
+ $ sudo gem install mongo
33
+
34
+ The source code is available at http://github.com/jimm/mongo-ruby-driver. You
35
+ can either clone the git repository or download a tarball or zip file. Once
36
+ you have the source, you can use it from wherever you downloaded it or you can
37
+ install it as a gem from the source by typing
38
+
39
+ $ rake gem:install
40
+
41
+
42
+ = Demo
43
+
44
+ You can see and run the examples if you've downloaded the source. Mongo must
45
+ be running, of course.
46
+
47
+ $ ruby examples/simple.rb
48
+
49
+ See also the test code, especially tests/test_db_api.rb.
50
+
51
+
52
+ = Testing
53
+
54
+ If you have the source code, you can run the tests.
55
+
56
+ $ rake test
57
+
58
+ The tests assume that the Mongo database is running on the default port.
59
+
60
+
61
+ = Documentation
62
+
63
+ This documentation is available online at http://mongo.rubyforge.org. You can
64
+ generate the documentation if you have the source by typing
65
+
66
+ $ rake rdoc
67
+
68
+ Then open the file html/index.html.
69
+
70
+
71
+ = Release Notes
72
+
73
+ See the git log comments.
74
+
75
+
76
+ = To Do
77
+
78
+ * Add group_by. Need to figure out how we are going to send functions. The
79
+ current thinking is that Mongo will allow a subset of JavaScript (which we
80
+ would have to send as a string), but this is still under discussion.
81
+
82
+ * Add explain and hint support.
83
+
84
+ * Only update message sizes once, not after every write of a value. This will
85
+ require an explicit call to update_message_length in each message subclass.
86
+
87
+ * Tests for update and repsert.
88
+
89
+ * Add a way to specify a collection of databases on startup (a simple array of
90
+ IP address/port numbers, perhaps, or a hash or something). The driver would
91
+ then find the master and, on each subsequent command, ask that machine if it
92
+ is the master before proceeding.
93
+
94
+ * Tests that prove that this driver's ObjectID and Geir's Java version do the
95
+ same thing. (I've done so manually.)
96
+
97
+ * Support more types: REF, SYMBOL, CODE_W_SCOPE, etc.
98
+
99
+ * Introduce optional per-database and per-collection PKInjector.
100
+
101
+ * More tests.
102
+
103
+ * Study src/main/ed/db/{dbcollection,dbcursor,db}.js and ByteEncoder.java in
104
+ the Babble code. That's what I should be writing to.
105
+
106
+
107
+ = Credits
108
+
109
+ Adrian Madrid, aemadrid@gmail.com
110
+ * bin/mongo_console
111
+ * examples/benchmarks.rb
112
+ * examples/irb.rb
113
+ * Modifications to examples/simple.rb
114
+ * Found plenty of bugs and missing features.
115
+ * Ruby 1.9 support.
116
+ * Gem support.
117
+ * Many other code suggestions and improvements.
118
+
119
+
120
+ = License
121
+
122
+ Copyright (C) 2008-2009 10gen Inc.
123
+
124
+ This program is free software: you can redistribute it and/or modify it under
125
+ the terms of the GNU Affero General Public License, version 3, as published by
126
+ the Free Software Foundation.
127
+
128
+ This program is distributed in the hope that it will be useful, but WITHOUT
129
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
130
+ FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
131
+ details.
132
+
133
+ See http://www.gnu.org/licenses for a copy of the GNU Affero General Public
134
+ License.
@@ -0,0 +1,86 @@
1
+ require 'rubygems'
2
+ require 'rubygems/specification'
3
+ require 'fileutils'
4
+ require 'rake'
5
+ require 'rake/testtask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/contrib/rubyforgepublisher'
8
+
9
+ GEM = "mongo"
10
+ GEM_VERSION = '0.0.1'
11
+ SUMMARY = 'Simple pure-Ruby driver for the 10gen Mongo DB'
12
+ DESCRIPTION = 'This is a simple pure-Ruby driver for the 10gen Mongo DB. For more information about Mongo, see http://www.mongodb.org.'
13
+ AUTHOR = 'Jim Menard'
14
+ EMAIL = 'jimm@io.com'
15
+ HOMEPAGE = 'http://www.mongodb.org'
16
+ RUBYFORGE_USER = 'jimm'
17
+
18
+ spec = Gem::Specification.new do |s|
19
+ s.name = GEM
20
+ s.version = GEM_VERSION
21
+ s.platform = Gem::Platform::RUBY
22
+ s.summary = SUMMARY
23
+ s.description = DESCRIPTION
24
+
25
+ s.require_paths = ['lib']
26
+
27
+ s.files = FileList['bin/*', 'lib/**/*.rb', 'tests/**/*.rb', '[A-Z]*'].to_a
28
+
29
+ s.bindir = 'bin'
30
+ s.executables = %w( mongo_console )
31
+ s.has_rdoc = true
32
+
33
+ s.author = AUTHOR
34
+ s.email = EMAIL
35
+ s.homepage = HOMEPAGE
36
+
37
+ s.rubyforge_project = GEM # GitHub bug, gem isn't being build when this miss
38
+ end
39
+
40
+ # NOTE: some of the tests assume Mongo is running
41
+ Rake::TestTask.new do |t|
42
+ t.test_files = FileList['tests/test*.rb']
43
+ end
44
+
45
+ desc "Generate documentation"
46
+ task :rdoc do
47
+ FileUtils.rm_rf('html')
48
+ system "rdoc --main README.rdoc --op html --inline-source --quiet README.rdoc `find lib -name '*.rb'`"
49
+ end
50
+
51
+ desc "Publish documentation to mongo.rubyforge.org"
52
+ task :publish => [:rdoc] do
53
+ # Assumes docs are in ./html
54
+ Rake::RubyForgePublisher.new(GEM, RUBYFORGE_USER).upload
55
+ end
56
+
57
+ namespace :gem do
58
+
59
+ Rake::GemPackageTask.new(spec) do |pkg|
60
+ pkg.gem_spec = spec
61
+ end
62
+
63
+ desc "Install the gem locally"
64
+ task :install => [:package] do
65
+ sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
66
+ end
67
+
68
+ desc "Install the gem locally with ruby 1.9"
69
+ task :'install19' => [:package] do
70
+ sh %{sudo gem19 install pkg/#{GEM}-#{GEM_VERSION}}
71
+ end
72
+
73
+ desc "Create a gemspec file"
74
+ task :make_spec do
75
+ File.open("#{GEM}.gemspec", "w") do |file|
76
+ file.puts spec.to_ruby
77
+ end
78
+ end
79
+
80
+ end
81
+
82
+ task :default => :list
83
+
84
+ task :list do
85
+ system 'rake -T'
86
+ end
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+ org_argv = ARGV.dup
3
+ ARGV.clear
4
+
5
+ require 'irb'
6
+
7
+ $LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib')
8
+ require 'mongo'
9
+
10
+ include XGen::Mongo::Driver
11
+
12
+ host = org_argv[0] || ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost'
13
+ port = org_argv[1] || ENV['MONGO_RUBY_DRIVER_PORT'] || XGen::Mongo::Driver::Mongo::DEFAULT_PORT
14
+ dbnm = org_argv[2] || ENV['MONGO_RUBY_DRIVER_DB'] || 'ruby-mongo-console'
15
+
16
+ puts "Connecting to #{host}:#{port} (CONN) on with database #{dbnm} (DB)"
17
+ CONN = Mongo.new(host, port)
18
+ DB = CONN.db(dbnm)
19
+
20
+ puts "Starting IRB session..."
21
+ IRB.start(__FILE__)
@@ -0,0 +1,7 @@
1
+ require 'mongo/mongo'
2
+ require 'mongo/objectid'
3
+ require 'mongo/message'
4
+ require 'mongo/db'
5
+ require 'mongo/cursor'
6
+ require 'mongo/collection'
7
+ require 'mongo/admin'
@@ -0,0 +1,86 @@
1
+ # --
2
+ # Copyright (C) 2008-2009 10gen Inc.
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify it
5
+ # under the terms of the GNU Affero General Public License, version 3, as
6
+ # published by the Free Software Foundation.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but WITHOUT
9
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
11
+ # for more details.
12
+ #
13
+ # You should have received a copy of the GNU Affero General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+ # ++
16
+
17
+ require 'mongo/util/ordered_hash'
18
+
19
+ module XGen
20
+ module Mongo
21
+ module Driver
22
+
23
+ # Provide administrative database methods: those having to do with
24
+ # profiling and validation.
25
+ class Admin
26
+
27
+ def initialize(db)
28
+ @db = db
29
+ end
30
+
31
+ # Return the current database profiling level.
32
+ def profiling_level
33
+ oh = OrderedHash.new
34
+ oh[:profile] = -1
35
+ doc = @db.db_command(oh)
36
+ raise "Error with profile command: #{doc.inspect}" unless @db.ok?(doc) && doc['was'].kind_of?(Numeric)
37
+ case doc['was'].to_i
38
+ when 0
39
+ :off
40
+ when 1
41
+ :slow_only
42
+ when 2
43
+ :all
44
+ else
45
+ raise "Error: illegal profiling level value #{doc['was']}"
46
+ end
47
+ end
48
+
49
+ # Set database profiling level to :off, :slow_only, or :all.
50
+ def profiling_level=(level)
51
+ oh = OrderedHash.new
52
+ oh[:profile] = case level
53
+ when :off
54
+ 0
55
+ when :slow_only
56
+ 1
57
+ when :all
58
+ 2
59
+ else
60
+ raise "Error: illegal profiling level value #{level}"
61
+ end
62
+ doc = @db.db_command(oh)
63
+ raise "Error with profile command: #{doc.inspect}" unless @db.ok?(doc)
64
+ end
65
+
66
+ # Return an array contining current profiling information from the
67
+ # database.
68
+ def profiling_info
69
+ @db.query(DB::SYSTEM_PROFILE_COLLECTION, Query.new({})).to_a
70
+ end
71
+
72
+ # Validate a named collection by raising an exception if there is a
73
+ # problem or returning +true+ if all is well.
74
+ def validate_collection(name)
75
+ doc = @db.db_command(:validate => name)
76
+ raise "Error with validate command: #{doc.inspect}" unless @db.ok?(doc)
77
+ result = doc['result']
78
+ raise "Error with validation data: #{doc.inspect}" unless result.kind_of?(String)
79
+ raise "Error: invalid collection #{name}: #{doc.inspect}" if result =~ /\b(exception|corrupt)\b/i
80
+ true
81
+ end
82
+
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,136 @@
1
+ # --
2
+ # Copyright (C) 2008-2009 10gen Inc.
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify it
5
+ # under the terms of the GNU Affero General Public License, version 3, as
6
+ # published by the Free Software Foundation.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but WITHOUT
9
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
11
+ # for more details.
12
+ #
13
+ # You should have received a copy of the GNU Affero General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+ # ++
16
+
17
+ require 'mongo/query'
18
+
19
+ module XGen
20
+ module Mongo
21
+ module Driver
22
+
23
+ # A named collection of records in a database.
24
+ class Collection
25
+
26
+ attr_reader :db, :name
27
+
28
+ def initialize(db, name)
29
+ @db = db
30
+ @name = name
31
+ end
32
+
33
+ # Return records that match a +selector+ hash. See Mongo docs for
34
+ # details.
35
+ #
36
+ # Options:
37
+ # :fields :: Array of collection field names; only those will be returned (plus _id if defined)
38
+ # :offset :: Start at this record when returning records
39
+ # :limit :: Maximum number of records to return
40
+ # :sort :: Either hash of field names as keys and 1/-1 as values; 1 ==
41
+ # ascending, -1 == descending, or array of field names (all
42
+ # assumed to be sorted in ascending order).
43
+ def find(selector={}, options={})
44
+ fields = options.delete(:fields)
45
+ fields = nil if fields && fields.empty?
46
+ offset = options.delete(:offset) || 0
47
+ limit = options.delete(:limit) || 0
48
+ sort = options.delete(:sort)
49
+ raise RuntimeError, "Unknown options [#{options.inspect}]" unless options.empty?
50
+ @db.query(@name, Query.new(selector, fields, offset, limit, sort))
51
+ end
52
+
53
+ # Insert +objects+, which are hashes. "<<" is aliased to this method.
54
+ def insert(*objects)
55
+ objects = objects.first if objects.size == 1 && objects.first.is_a?(Array)
56
+ res = @db.insert_into_db(@name, objects)
57
+ res.size > 1 ? res : res.first
58
+ end
59
+ alias_method :<<, :insert
60
+
61
+ # Remove the records that match +selector+.
62
+ def remove(selector={})
63
+ @db.remove_from_db(@name, selector)
64
+ end
65
+
66
+ # Remove all records.
67
+ def clear
68
+ remove({})
69
+ end
70
+
71
+ # Update records that match +selector+ by applying +obj+ as an update.
72
+ # If no match, inserts (???).
73
+ def repsert(selector, obj)
74
+ @db.repsert_in_db(@name, selector, obj)
75
+ end
76
+
77
+ # Update records that match +selector+ by applying +obj+ as an update.
78
+ def replace(selector, obj)
79
+ @db.replace_in_db(@name, selector, obj)
80
+ end
81
+
82
+ # Update records that match +selector+ by applying +obj+ as an update.
83
+ # Both +selector+ and +modifier_obj+ are required.
84
+ def modify(selector, modifier_obj)
85
+ raise "no object" unless modifier_obj
86
+ raise "no selector" unless selector
87
+ @db.modify_in_db(@name, selector, modifier_obj)
88
+ end
89
+
90
+ # Create a new index named +index_name+. +fields+ should be an array
91
+ # of field names.
92
+ def create_index(name, *fields)
93
+ @db.create_index(@name, name, fields)
94
+ end
95
+
96
+ # Drop index +name+.
97
+ def drop_index(name)
98
+ @db.drop_index(@name, name)
99
+ end
100
+
101
+ # Drop all indexes.
102
+ def drop_indexes
103
+ # just need to call drop indexes with no args; will drop them all
104
+ @db.drop_index(@name, '*')
105
+ end
106
+
107
+ # Return an array of hashes, one for each index. Each hash contains:
108
+ #
109
+ # :name :: Index name
110
+ #
111
+ # :keys :: Hash whose keys are the names of the fields that make up
112
+ # the key and values are integers.
113
+ #
114
+ # :ns :: Namespace; same as this collection's name.
115
+ def index_information
116
+ @db.index_information(@name)
117
+ end
118
+
119
+ # Return a hash containing options that apply to this collection.
120
+ # 'create' will be the collection name. For the other possible keys
121
+ # and values, see DB#create_collection.
122
+ def options
123
+ @db.collections_info(@name).next_object()['options']
124
+ end
125
+
126
+ # Return the number of records that match +selector+. If +selector+ is
127
+ # +nil+ or an empty hash, returns the count of all records.
128
+ def count(selector={})
129
+ @db.count(@name, selector || {})
130
+ end
131
+
132
+ end
133
+ end
134
+ end
135
+ end
136
+