
=pod

=head1 NAME

MongoDB::Tutorial - Getting started with MongoDB

=head1 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 L<http://www.mongodb.org>.

=head1 TERMINOLOGY

Document-oriented database terms and their relational equivalents:

=over

=item Database

Database

=item Collection

Table

=item Document

Record or row

=item L<MongoDB::OID>

Autoincrementing primary key

=back

=head1 PREAMBLE

C<use MongoDB> loads most of the packages you'll need to interact with MongoDB:
L<MongoDB::Connection>, L<MongoDB::Database>, L<MongoDB::Collection>, and
L<MongoDB::Cursor>.  To use special Mongo data types (see
L<MongoDB::DataTypes>), you have to include them separately.  So, usually, to
use Mongo, you'll start with at least:

    use MongoDB;
    use MongoDB::OID;

=head1 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
L<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->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->users;

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

=head1 CRUD

=head2 Creating Documents

Before you get started with MongoDB, it is important to know that, by default,
MongoDB does not return a response from writes (inserts, updates, and deletes).
If you would like to know if the insert succeeded or failed, use the C<safe>
option.  For more information on this, see
L<http://www.mongodb.org/display/DOCS/getLastError+Command> for details.

=head3 Inserting

To add a document to the collection, we use the C<insert> function.  It takes a
hash which is saved to the collection.

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

Now there is a user in the collection.

=head3 L<MongoDB::OID>s

When a document is inserted, it is given a C<_id> field if one does not already
exist.  By default, this field is a L<MongoDB::OID>, 12 bytes that are
guaranteed to be unique. The C<_id> field of the inserted document is returned
by the C<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 C<batch_insert>, which returns an array of the C<_id> fields of the
documents inserted.

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


=head2 Retrieving Documents

=head3 Queries

To retrieve documents that were saved to a collection, we can use the C<find>
method.

    my $all_users = $users->find;

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->find({"name" => "Joe"});

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

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

=head3

This being Perl, it is important to mention that you can also use regular
expressions to search for strings.  If you wanted to find all users with the
name John and all variations of said name, you could do:

    my $john = $users->find({"name" => qr/joh?n/i});

See L<MongoDB::DataTypes/"Regular Expressions"> for more information.

=head3 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->find({'x' => { '$lt' => 4 }});

Comparison operators can be combined to get a range:

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


=head3 Cursors

C<find> returns a L<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";


=head2 Updating Documents

=head3 C<$>-operators

To change a document after it has been saved to the database, you must pass
C<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 C<$push>.  So, to add an element to
the C<"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
C<$set>.  For example, to change the _id field to a username, we would say:

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

=head3 Options

By default, C<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 C<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"},
        {'$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.

=head2 Deleting Documents

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

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

Calling C<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 C<drop>:

    $users->drop;

C<drop> can also be used for whole databases:

    $db->drop;

=head1 MONGO BASICS

=head2 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 not
recognize the command if they are not ordered command name first. Thus, if you
are running a database command, you should probably use L<Tie::IxHash> instead of a
normal hash (normal hashes are not ordered).

For example, you can use a database command to create a capped collection like
so:

    my $cmd = Tie::IxHash->new("create" => "posts",
        "capped" => boolean::true,
        "size" => 10240,
        "max" => 100);

    $db->run_command($cmd);

This will create a capped collection called "posts" in the current database.  It
has a maximum size of 10240 bytes and can contain up to 100 documents.

=head1 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
(L<http://www.mongodb.org>) into Perl.

Check out L<MongoDB::Examples> for more examples.
