
=pod

=head1 NAME

MongoDB::Examples - Some examples of MongoDB syntax

=head1 MAPPING SQL TO MONGODB

For developers familiar with SQL, the following chart should help you see how
many common SQL queries could be expressed in MongoDB. 

These are Perl-specific examples of translating SQL queries to MongoDB's query
language.  To see the JavaScript (or other languages') mappings, see 
L<http://dochub.mongodb.org/core/sqlToMongo>.

=over

=item C<CREATE TABLE USERS (a Number, b Number)>
Implicit, can be done explicitly.

=item C<INSERT INTO USERS VALUES(1,1)>

    $db->users->insert({a => 1, b => 1});

=item C<SELECT a,b FROM users>

    $db->users->find({}, {a => 1, b => 1});

=item C<SELECT * FROM users>

    $db->users->find;

=item C<SELECT * FROM users WHERE age=33>

    $db->users->find({age => 33})

=item C<SELECT a,b FROM users WHERE age=33>

    $db->users->find({age => 33}, {a => 1, b => 1});

=item C<SELECT * FROM users WHERE age=33 ORDER BY name>

    $db->users->find({age => 33}).sort({name => 1});

=item C<<SELECT * FROM users WHERE age>33>>

    $db->users->find({age => {'$gt' => 33}})

=item C<<SELECT * FROM users WHERE age<33>>

    $db->users->find({age => {'$lt' => 33}})

=item C<SELECT * FROM users WHERE name LIKE "%Joe%">

    $db->users->find({name => qr/Joe/});

=item C<SELECT * FROM users WHERE name LIKE "Joe%">

    $db->users->find({name => qr/^Joe/});

=item C<<SELECT * FROM users WHERE age>33 AND age<=40>>

    $db->users->find({age => {'$gt' => 33, '$lte' => 40}});

=item C<SELECT * FROM users ORDER BY name DESC>

    $db->users->find->sort({name => -1});

=item C<CREATE INDEX myindexname ON users(name)>

    $db->users->ensure_index({name => 1});

=item C<CREATE INDEX myindexname ON users(name,ts DESC)>

    $db->users->ensure_index(Tie::IxHash->new(name => 1, ts => -1));

=item C<SELECT * FROM users WHERE a=1 and b='q'>

    $db->users->find({a => 1, b => "q"});

=item C<SELECT * FROM users LIMIT 10 SKIP 20>

    $db->users->find->limit(10)->skip(20);

=item C<SELECT * FROM users WHERE a=1 or b=2>

    $db->users->find({'$or' => ({a => 1}, {b => 2})});

=item C<SELECT * FROM users LIMIT 1>

    $db->users->find->limit(1);

=item C<EXPLAIN SELECT * FROM users WHERE z=3>

    $db->users->find({z => 3})->explain;

=item C<SELECT DISTINCT last_name FROM users>

    $db->run_command({distinct => "users", key => "last_name"});

=item C<SELECT COUNT(*y) FROM users>

    $db->users->count;

=item C<<SELECT COUNT(*y) FROM users where age > 30>>

    $db->users->find({"age" => {'$gt' => 30}})->count;

=item C<SELECT COUNT(age) from users>

    $db->users->find({age => {'$exists' => 1}})->count;

=item C<UPDATE users SET a=1 WHERE b='q'>

    $db->users->update({b => "q"}, {'$set' => {a => 1}});

=item C<UPDATE users SET a=a+2 WHERE b='q'>

    $db->users->update({b => "q"}, {'$inc' => {a => 2}});

=item C<DELETE FROM users WHERE z="abc">

    $db->users->remove({z => "abc"});

=back

=head1 DATABASE COMMANDS

=head2 Distinct

The distinct command returns all values for a given key in a collection.  For 
example, suppose we had a collection with the following documents (C<_id> value
ignored):

    { 'name' => 'a', code => 1 }
    { 'name' => 'b', code => 1 }
    { 'name' => 'c', code => 2 }
    { 'name' => 'd', code => "3" }

If we wanted to see all of values in the "code" field, we could run:

    my $result = $db->run_command([
       "distinct" => "collection_name",
       "key"      => "code",
       "query"    => {}
    ]);

Notice that the arguments are in an array, to ensure that their order is 
preserved.  You could also use a L<Tie::IxHash>.

C<query> is an optional argument, which can be used to only run C<distinct> on
specific documents.  It takes a hash (or L<Tie::IxHash> or array) in the same 
form as L<MongoDB::Collection/"find($query)">.

Running C<distinct> on the above collection would give you:

    {
        'ok' => '1',
        'values' => [
                      1,
                      2,
                      "3"
                    ]
    };

=head2 MapReduce

MapReduce is a powerful aggregation tool.  (For traditional queries, you should
use C<MongoDB::Collection::query>.)  

This example counts the number of occurences of each tag in a collection.  Each
document contains a "tags" array that contains zero or more strings.

    my $map = <<MAP;
    function() {
        this.tags.forEach(function(tag) {
            emit(tag, {count : 1});
        });
    }
    MAP
    
    my $reduce = <<REDUCE;
    function(prev, current) {
        result = {count : 0};
        current.forEach(function(item) {
            result.count += item.count;
        });
        return result;
    }
    REDUCE
    
    my $cmd = Tie::IxHash->new("mapreduce" => "foo",
        "map" => $map,
        "reduce" => $reduce);
    
    my $result = $db->run_command($cmd);

See the MongoDB documentation on MapReduce for more information
(L<http://dochub.mongodb.org/core/mapreduce>).

=head1 UPDATING

=head2 Positional Operator

In MongoDB 1.3.4 and later, you can use positional operator, C<$>, to update 
elements of an array.  For instance, suppose you have an array of user 
information and you want to update a user's name.

A sample document in JavaScript:

    {
        "users" : [
            {
                "name" : "bill",
                "age" : 60
            },
            {
                "name" : "fred",
                "age" : 29
            },
        ]
    }

The update:

    $coll->update({"users.name" => "fred"}, {'users.$.name' => "george"});

This will update the array so that the element containing C<"name" =E<gt> "fred"> 
now has C<"name" =E<gt> "george">.
