MongoDB is an open-source NoSQL document database. In this article we see the basics: How to insert a document in a MongoDB collection and how to update a document.

Inserting elements

The most simple example is inserting two element in a collection.

examples/mongodb_insert_two_elements.pl

use strict;
use warnings;
use 5.010;

use MongoDB ();
use Data::Dumper qw(Dumper);

my $client = MongoDB::MongoClient->new(host => 'localhost', port => 27017);
my $db   = $client->get_database( 'example_' . $$ . '_' . time  );

my $people_coll = $db->get_collection('people');

$people_coll->insert_one( {
    name => 'First',
});

$people_coll->insert_one( {
    name => 'Second',
});

my $people = $people_coll->find;
while (my $p = $people->next) {
    print Dumper $p;
}

$db->drop;

my $client = MongoDB::MongoClient->new(host => 'localhost', port => 27017); connects to the MongoDB server running on the same machine at the default port.

The next call: my $db = $client->get_database( 'example_' . $$ . '_' . time ); returns a database. In order to reduce the chances that we access an already existing database we create the name of the database on the fly using the current process id $$ and the current time in seconds.

Once we have the database object in $db we fetch the collection which is similar to tables in relational databases, with the big difference that we don't need to execute special commands to create it or to set up a schema: my $people_coll = $db->get_collection('people');

The next two calls insert data structures (hash references) in the collection. In the terminology of MongoDB they are called documents:

$people_coll->insert_one( {
    name => 'First',
});

$people_coll->insert_one( {
    name => 'Second',
});

Then we call find to fetch all the documents. It returns an object that can be used to iterate over all the documents returned by find using the next method of the object.

my $people = $people_coll->find;
while (my $p = $people->next) {
    print Dumper $p;
}

On every iteration this return a hash reference (stored in $p) that contains the document. We use Data::Dumper to print them out:

$VAR1 = {
          '_id' => bless( {
                          'value' => '52861f9602490acc35000000'
                        }, 'MongoDB::OID' ),
          'name' => 'First'
        };
$VAR1 = {
          '_id' => bless( {
                          'value' => '52861f9602490acc35000001'
                        }, 'MongoDB::OID' ),
          'name' => 'Second'
        };

In addition to the data we inserted, each document also contains another field called _id that is the unique id of this document, called the ObjectIDd. (but read the specification for more, well, specific details.)

The last statement in this example is $db->drop;. As the name might let you guess, it will drop the database so we won't have lots of example databases hanging around.

Manually dropping a database

If for some reason the database is not dropped at the end of the script (e.g. if there was an exception in the code we can manually drop the database using the mongo command line client:

$ mongo
MongoDB shell version: 2.4.6
connecting to: test
> show dbs
demo   0.078125GB
dev_site  0.203125GB
example_13930_1384522288   0.203125GB
local   0.078125GB

> use example_13930_1384522288
switched to db example_13930_1384522288

> db.dropDatabase()
{ "dropped" : "example_13930_1384522288", "ok" : 1 }

> show dbs
demo   0.078125GB
dev_site   0.203125GB
local  0.078125GB

> exit
bye
$

show dbs will list all the databases. (There were 4 in this MongoDB installation)

use example_13930_1384522288 switches to the database.

db.dropDatabase() drops the database and

exit, quits the client.

Dropping the database at the END

Another idea might be to put the database dropping code in an END block:

END {
    $db->drop if $db;
}

That will ensure that the database is dropped even if there was an exception in the code.

The if was added so we won't call drop if for some reason we don't even have a database object.

Update one of the documents

Now that we know how to insert data, let's see an example to update one of the documents. After the second call to insert I added this code:

$people_coll->update(
    { name => 'Second'},
    { '$set' => {
            phone => '1-123',
        },
    },
);

update gets two hash references. The first one { name => 'Second'} is the selector (what would be a WHERE-clause in SQL). It means, update the document where the "name" field equals to 'Second'.

The second hash reference does the actual update. '$set' is a MongoDB command that tells the database engine to set a value. The { phone => '1-123'} part tells to set the phone field to be '1-123'. Regardless if it existed or not before.

The output now looks like this:

$VAR1 = {
          'name' => 'First',
          '_id' => bless( {
                          'value' => '52862563527197d436000000'
                        }, 'MongoDB::OID' )
        };
$VAR1 = {
          'name' => 'Second',
          '_id' => bless( {
                          'value' => '52862563527197d436000001'
                        }, 'MongoDB::OID' ),
          'phone' => '1-123'
        };

The ObjectIds has changed because this was a new run. That's not the point of this example.

The interesting part is that the second document now has both a 'name' and a 'phone' field while the first document only has a 'name'.