- Introducing the MongoDB API through Ruby
- Understanding how the drivers work
- Using the BSON format and MongoDB network protocol
Installing and connecting
Update yum database with dnf
using the following command.
sudo dnf makecache --refresh
After updating yum database, We can install rubygem-mongo
using dnf
by running the following command:
sudo dnf -y install rubygem-mongo
To uninstall only the rubygem-mongo
package we can use the following command:
sudo dnf remove rubygem-mongo
OR
Update yum database with yum
using the following command.
sudo yum makecache --refresh
After updating yum database, We can install rubygem-mongo
using yum
by running the following command:
sudo yum -y install rubygem-mongo
Once you have RubyGems installed, run:
gem install mongo
Issue:
[root@DBAMAXWELL ~]# gem install mongo
Building native extensions. This could take a while...
ERROR: Error installing mongo:
ERROR: Failed to build gem native extension.
current directory: /usr/local/share/gems/gems/bson-4.14.1/ext/bson
/usr/bin/ -r ./siteconf20220325-427526-vfnj46.rb extconf.rb
mkmf.rb can't find header files for ruby at /usr/share/include/ruby.h
extconf failed, exit code 1
Gem files will remain installed in /usr/local/share/gems/gems/bson-4.14.1 for inspection.
Results logged to /usr/local/lib64/gems/ruby/bson-4.14.1/gem_make.out
Solution:
[root@DBAMAXWELL ~]# yum install ruby-devel
Last metadata expiration check: 1:48:48 ago on Fri 25 Mar 2022 05:54:43 PM CST.
Dependencies resolved.
===============================================================================================================================================================================================================
Package Architecture Version Repository Size
===============================================================================================================================================================================================================
Installing:
ruby-devel x86_64 2.5.9-109.module_el8.5.0+1097+b05a0601 appstream 126 k
Transaction Summary
===============================================================================================================================================================================================================
Install 1 Package
Total download size: 126 k
Installed size: 294 k
Is this ok [y/N]: y
Downloading Packages:
[MIRROR] ruby-devel-2.5.9-109.module_el8.5.0+1097+b05a0601.x86_64.rpm: Curl error (28): Timeout was reached for http://centosg9.centos.org/centos/8-stream/AppStream/x86_64/os/Packages/ruby-devel-2.5.9-109.module_el8.5.0%2b1097%2bb05a0601.x86_64.rpm [Operation too slow. Less than 1000 bytes/sec transferred the last 30 seconds]
ruby-devel-2.5.9-109.module_el8.5.0+1097+b05a0601.x86_64.rpm 1.6 kB/s | 126 kB 01:17
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Total 1.6 kB/s | 126 kB 01:18
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : ruby-devel-2.5.9-109.module_el8.5.0+1097+b05a0601.x86_64 1/1
Running scriptlet: ruby-devel-2.5.9-109.module_el8.5.0+1097+b05a0601.x86_64 1/1
Verifying : ruby-devel-2.5.9-109.module_el8.5.0+1097+b05a0601.x86_64 1/1
Installed:
ruby-devel-2.5.9-109.module_el8.5.0+1097+b05a0601.x86_64
Complete!
[root@DBAMAXWELL ~]# gem install mongo
Building native extensions. This could take a while...
Successfully installed bson-4.14.1
Fetching: mongo-2.17.0.gem (100%)
Successfully installed mongo-2.17.0
2 gems installed
[root@DBAMAXWELL ~]#
You'll start by connecting to .First,make sure that mongod is running by running the mongo shell to ensure you can connect . Next,create a file called connect.rb and enter the following code:
require 'rubygems'
require 'mongo'
$client = Mongo::Client.new([ '127.0.0.1:27017' ], :database => 'tutorial') Mongo::Logger.logger.level = ::Logger::ERROR
$users = $client[:users]
puts 'connected!'
The first two require statements ensure that you've loaded the driver.The next three lines instantiate the client to localhost and connect to the tutorial database,store a reference to the users collection in the $users variable, and print the string connected! we place a $ in front of each variable to make it global so that it'll be accessible outside of the connect.rb script.Save the file and run it:
[root@DBAMAXWELL ~]# chmod 775 connect.rb
[root@DBAMAXWELL ~]# ruby connect.rb
connected!
[root@DBAMAXWELL ~]#
[root@DBAMAXWELL ~]# irb -r ./connect.rb
connected!
irb(main):012:0> id = $users.insert_one({"last_name" => "mtsouk"})
=> #<Mongo::Operation::Insert::Result:0x46917215911640 documents=[{"n"=>1, "ok"=>1.0}]>
irb(main):013:0> $users.find().each do |user|
irb(main):014:1* puts user
irb(main):015:1> end
{"_id"=>BSON::ObjectId('623de3217c6c25a6d51def51'), "last_name"=>"mtsouk"}
=> #<Mongo::Cursor:0x46917214326540 @view=#<Mongo::Collection::View:0x46917214463440 namespace='tutorial.users' @filter={} @options={}>>
irb(main):016:0> smith = {"last_name" => "smith","age" => 30}
=> {"last_name"=>"smith", "age"=>30}
irb(main):017:0> jones = {"last_name" => "jones","age" => 40}
=> {"last_name"=>"jones", "age"=>40}
irb(main):018:0> smith_id = $users.insert_one(smith)
=> #<Mongo::Operation::Insert::Result:0x69912303817880 documents=[{"n"=>1, "ok"=>1.0}]>
irb(main):019:0> jones_id = $users.insert_one(jones)
=> #<Mongo::Operation::Insert::Result:0x69912303763600 documents=[{"n"=>1, "ok"=>1.0}]>
irb(main):020:0> $users.find("age" => {"$gt" => 20}).each.to_a do |row|
irb(main):021:1* puts row
irb(main):022:1> end
=> [{"_id"=>BSON::ObjectId('623de43b7c6c25a6d51def52'), "last_name"=>"smith", "age"=>30}, {"_id"=>BSON::ObjectId('623de4547c6c25a6d51def53'), "last_name"=>"jones", "age"=>40}]
irb(main):023:0>
Queries and cursors
irb(main):033:0> $users.find({"last_name" => "smith"}).to_a
=> [{"_id"=>BSON::ObjectId('623de43b7c6c25a6d51def52'), "last_name"=>"smith", "age"=>30}]
irb(main):034:0> $users.find({"age" => {"$gt" => 30}}).to_a
=> [{"_id"=>BSON::ObjectId('623de4547c6c25a6d51def53'), "last_name"=>"jones", "age"=>40}]
irb(main):035:0> $users.find({"age" => {"$gt" => 30}})
=> #<Mongo::Collection::View:0x69912370371560 namespace='tutorial.users' @filter={"age"=>{"$gt"=>30}} @options={}>
irb(main):036:0> cursor = $users.find({"age" => {"$gt" => 30}})
=> #<Mongo::Collection::View:0x46917216089580 namespace='tutorial.users' @filter={"age"=>{"$gt"=>30}} @options={}>
irb(main):040:0> cursor = $users.find({"age" => {"$gt" => 30}})
=> #<Mongo::Collection::View:0x46917213629260 namespace='tutorial.users' @filter={"age"=>{"$gt"=>30}} @options={}>
irb(main):041:0> cursor.each do |doc|
irb(main):042:1* puts doc["last_name"]
irb(main):043:1> end
jones
=> #<Mongo::Cursor:0x46917213420200 @view=#<Mongo::Collection::View:0x46917213629260 namespace='tutorial.users' @filter={"age"=>{"$gt"=>30}} @options={}>>
Updates and deletes
updates requires at least two arguments: a query selector and an update document
irb(main):059:0> $users.find({"last_name" => "smith"}).update_one({"$set" => {"city" => "Chicago"}})
=> #<Mongo::Operation::Update::Result:0x46917213238900 documents=[{"n"=>1, "nModified"=>1, "ok"=>1.0}]>
irb(main):060:0> $users.find({"last_name" => "smith"}).to_a
=> [{"_id"=>BSON::ObjectId('623de43b7c6c25a6d51def52'), "last_name"=>"smith", "age"=>30, "city"=>"Chicago"}]
irb(main):061:0> $users.find({"last_name" => "smith"}).to_a
=> [{"_id"=>BSON::ObjectId('623de43b7c6c25a6d51def52'), "last_name"=>"smith", "age"=>30, "city"=>"Chicago"}]
irb(main):062:0>
if you want to apply the update to all smith documents , you must replace the update_one with update_many method:
irb(main):063:0> $users.find({"last_name"=>"smith"}).update_many({"$set" => {"city" => "Chicago"}})
=> #<Mongo::Operation::Update::Result:0x46917215794940 documents=[{"n"=>1, "nModified"=>0, "ok"=>1.0}]>
irb(main):064:0> $users.find({"age" => {"$gte" => 40}}).delete_one
=> #<Mongo::Operation::Delete::Result:0x46917213608100 documents=[{"n"=>1, "ok"=>1.0}]>
if you want to delete all documents matching the criteria,you'd have to run this:
irb(main):065:0> $users.find({"age" => {"$gte" => 40}}).delete_many
=> #<Mongo::Operation::Delete::Result:0x46917211989700 documents=[{"n"=>0, "ok"=>1.0}]>
with no arguments, the drop method deletes all remaining documents:
irb(main):066:0> $users.drop
=> #<Mongo::Operation::Result:0x46917211639180 documents=[{"nIndexesWas"=>1, "ns"=>"tutorial.users", "ok"=>1.0}]>
irb(main):067:0>
To drop a collection and all its indexes,use the drop_collection method:(users has been dropped, it displayed false as below)
irb(main):004:0> db = $client.use('tutorial')
=> #<Mongo::Client:0x70007027772580 cluster=#<Cluster topology=Single[127.0.0.1:27017] servers=[#<Server address=127.0.0.1:27017 STANDALONE pool=#<ConnectionPool size=1 (0-5) used=0 avail=1 pending=0>>]>>
irb(main):005:0> db['users'].drop
=> false
irb(main):006:0>
Database commands
First ,you instantiate a Ruby database object referencing the admin database.You then pass the command's query specification to the command method.
irb(main):001:0> $admin_db = $client.use('admin')
=> #<Mongo::Client:0x70007027469800 cluster=#<Cluster topology=Single[127.0.0.1:27017] servers=[#<Server address=127.0.0.1:27017 STANDALONE pool=#<ConnectionPool size=0 (0-5) used=0 avail=0 pending=0>>]>>
irb(main):002:0> $admin_db.command({"listDatabases" => 1})
=> #<Mongo::Operation::Result:0x47408727126480 documents=[{"databases"=>[{"name"=>"admin", "sizeOnDisk"=>40960.0, "empty"=>false}, {"name"=>"config", "sizeOnDisk"=>36864.0, "empty"=>false}, {"name"=>"local", "sizeOnDisk"=>40960.0, "empty"=>false}], "totalSize"=>118784.0, "ok"=>1.0}]>
irb(main):003:0>
How the drivers work?
All MongoDB drivers perform three major functions:
- generate MongoDB object IDs.
- convert any language-specific representation of documents to and from BSON,the binary data format used by MongoDB.
- communicate with the database over a TCP socket using the MongoDB wire protocol.
object ID generation
Every MongoDB document requires a primary key. which must be unique for all documents in each collection,is stored in the document's _id field.
You can call on object ID's generation_time method to get that ID's creation time as a Ruby Time object.
irb(main):009:0> require 'mongo'
=> false
irb(main):010:0> id = BSON::ObjectId.from_string('4c291856238d3b19b2000001')
=> BSON::ObjectId('4c291856238d3b19b2000001')
irb(main):011:0> id.generation_time
=> 2010-06-28 21:47:02 UTC
irb(main):012:0>
irb(main):012:0> jun_id = BSON::ObjectId.from_time(Time.utc(2022, 3, 26))
=> BSON::ObjectId('623e57800000000000000000')
irb(main):013:0> March_id = BSON::ObjectId.from_time(Time.utc(2022, 3, 20))
=> BSON::ObjectId('62366e800000000000000000')
irb(main):014:0>