NAME

MongoDB::Tutorial - Getting started with MongoDB

DESCRIPTION

The tutorial runs through the basic functionality of the MongoDB package. This is a good starting point if you have never used MongoDB before.

The tutorial assumes that you are running a Mongo database server locally on the default port. You can download Mongo from http://www.mongodb.org.

TERMINOLOGY

Document-oriented database terms and their relational equivalents:

Database

Database

Collection

Table

Document

Record or row

MongoDB::OID

Autoincrementing primary key

CONNECTING

To get started, we have to connect to the database server. Because it's running locally on the default port, we need not pass any parameters to the MongoDB::Connection constructor:

my $conn = MongoDB::Connection->new;

Now we're connected to the database server. Next we need a database to work with, we'll call it "tutorial". You need not do anything special to create the database, Mongo will create it on the fly.

my $db = $conn->get_database("tutorial");

The last part of the preliminary setup is to choose a collection. We'll be using the "users" collection to start out.

my $users = $db->get_collection("users");

Again, there is no need to create the collection in advance, it will be created as needed.

CRUD

Creating Documents

Inserting

To add a document to the collection, we use the insert function. It takes a hash, which it saves to the collection.

$users->insert({"name" => "Joe", 
    "age" => 52, 
    "likes" => [qw/skiing math ponies/]});

Now there is a user in the collection.

MongoDB::OIDs

When a document is inserted, it is given an _id field if one does not already exist. By default, this field is a MongoDB::OID, 12 bytes that are guaranteed to be unique. The _id field of the inserted document is returned by the insert method.

my $id = $users->insert({"name" => "Bill"});

An efficient way to insert documents is to send many at a time to the database by using batch_insert, which returns an array of the _id fields of the documents inserted.

@ids = $users->batch_insert(\@fifty_users);

Retrieving Documents

Queries

To retrive documents that were saved to a collection, we can use the query method.

my $all_users = $users->query;

To query for certain criteria, say, all users named Joe, pass the query a hash with the key/value pair you wish to match:

my $some_users = $users->query({"name" => "Joe"});

You can match array elements in your querys; for example, to find all users who like math:

my $geeks = $users->query({"likes" => "math"});

Ranges

As queries are hashes, they use a special syntax to express comparisons, such as "x < 4". To make the query a valid hash, Mongo uses $-prefixed terms. For example, "x < 4" could be expressed by:

my $doc321 = $collection->query({'x' => { '$lt' => 4 }});

Comparison operators can be combined to get a range:

my $doc32 = $collection->query({'x' => { '$gte' => 2, '$lt' => 4 }});

Cursors

query returns a MongoDB::Cursor, which can be iterated over. It lazily loads results from the database. The following prints all of the users' names:

while (my $doc = $all_users->next) {
    print $doc->{'name'}."\n";
}

A cursor can also be converted into an array of hash references. For example, to print the "name" field of the first result:

my @arr = $geeks->all;
print $arr[0]->{'name'}."\n";

Updating Documents

$-operators

To change a document after it has been saved to the database, you must pass update two arguments. The first is a query argument, identical to the previous section, to identify the document you want to change. The second is an argument that describes the change that you wish to make.

The change is described by $-prefixed descriptors. For example, to increment a field, we would write:

$users->update({"_id" => $id}, {'$inc' => {'age' => 1}});

To add an element to an array, we can use $push. So, to add an element to the "likes" array, we write:

$users->update({"_id" => $id}, {'$push' => {'likes' => 'reading'}});

To add a new field or change the type or value of an existing field, we use $set. For example, to change the _id field to a username, we would say:

$users->update({"_id" => $id}, {'$set' => {'_id' => 'joe_schmoe'}});

Options

By default, update operates on one matching document, and does nothing if no document matches the query. There are two options available to change this behavior.

Suppose we want to add a "gift" field to everyone whose birthday it is today. One way would be to find every person whose birthday it was and iterate through the user documents, updating each one. However, it would be much faster and easier to update multiple documents at once. We can do this by using an optional third parameter with update:

my $today = DateTime->now;
my $tomorrow = DateTime->now->set('day' => $today->day+1);

$users->update({"bday" => {'$gte' => $today, '$lte' => $tomorrow}}, 
    {'$set' => {'gift' => $gift}},
    {'multiple' => 1});

(This functionality was added in version 1.1.3 of the database and will not work in earlier versions.) Sometimes we may want update to create an element if it does not already exist. This is called an 'upsert' (as it is a combination of an update and an insert). For example, the same code could be used for creating and updating a log document:

$pageviews->update({"url" => "www.example.com"},
    {"url" => "www.example.com", '$inc' => {"views" => 1}},
    {'upsert' => 1});

If the pageview counter for www.example.com did not exist yet, it would be created and the "views" field would be set to 1. If it did exist, the "views" field would be incremented.

Deleting Documents

To delete documents, we use the remove method. It takes the same type of hash queries do:

$users->remove({"name" => "Joe"});

Calling remove with no parameters removes all of the objects in a collection. It does not delete the collection, though (in that in that it will still appear if the user lists collections in the database and the indexes will still exist). To remove a collection entirely, call drop:

$users->drop;

drop can also be used for whole databases:

$db->drop;

MONGO BASICS

Indexes

Creating an Index

Unique and non-unique indexes can be created on collections using MongoDB::Collection::ensure_index.

For example, to create a non-unique index on x:

$collection->ensure_index({'x' => 1})

To create a unique index on y:

$collection->ensure_index({"y" => 1}, {"unique" => 1});

Multi-key indexes can be created to speed up queries like "sort by name, then by age." Index direction (1 or -1) is only important for multi-key indexes and should be the sort order. So, for example, if we want a fast sort by name ascending and age descending, we'd write:

my $idx = Tie::IxHash->new(name => 1, age => -1);
$collection->ensure_index($idx);

Keep in mind that you should use Tie::IxHash for multi-key indexes to guarantee the keys will be saved in the correct order.

Database Commands

There are a large number of useful database commands that can be called directly with $db->run_command. For example, to drop a collection, you can use:

$db->run_command({drop => $collection_name});

"drop" only requires one key/value pair, but for commands that require multiple fields, Mongo expects key/value pairs to be in a certain order. It will no recognize the command if they are not ordered command name first. Thus, if you are running a database command, you should probably use Tie::IxHash instead of a normal hash (normal hashes are not ordered).

NEXT STEPS

Now that you know the basic syntax used by the Perl driver, you should be able to translate the JavaScript examples in the main MongoDB documentation (http://www.mongodb.org) into Perl.

If there's anything else you'd like to see as part of the tutorial or documentation in general, please contact kristina@mongodb.org.