In this example we'll see how to insert a document in MongoDB. How to find a document based on an internal key-value pair, and how to delete a document based on similar conditions.

Example

examples/mongodb_insert_delete.pl

#!/usr/bin/perl
use strict;
use warnings;
use 5.010;

use MongoDB;

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

my $database = $client->get_database($db_name);
my $collection = $database->get_collection('data');

$collection->insert_one({
    cpan => {
        name => 'Foo',
        version => 1,
    },
});

$collection->insert_one({
    cpan => {
        name => 'Foo',
        version => 2,
    },
});

$collection->insert_one({
    cpan => {
        name => 'Bar',
        version => 1,
    },
});

say '-----';
foreach my $e ($collection->find->all) {
    say "$e->{cpan}{name} $e->{cpan}{version}";
}

say '-----';
foreach my $e ($collection->find({ 'cpan.name' => 'Foo' })->all) {
    say "$e->{cpan}{name} $e->{cpan}{version}";
}

$collection->delete_one({ 'cpan.version' => 2 });

say '-----';
foreach my $e ($collection->find({ 'cpan.name' => 'Foo' })->all) {
    say "$e->{cpan}{name} $e->{cpan}{version}";
}

$database->drop;

Explanation

After loading the MongoDB module into memory We connect to the MongoDB server, using the MongoDB::MongoClient module.

We 'create' a database name based on the process ID and timestamp. This level of uniqueness is good enough for our purposes and in general I think this is good enough for test cases. In the end, even 'testing' would be ok, but I wanted to reduce the chances I reuse another database I used for another example. It is also not really 'creating' the database as the database will only be created when we actually insert some data. The last line in this first section is getting access to a collection called 'data'. We could have used any name here.

use MongoDB;

my $client = MongoDB::MongoClient->new( host => 'localhost', port => 27017 );
my $db_name = 'example_' . $$ . '_' . time;
#say $db_name;
my $database = $client->get_database($db_name);
my $collection = $database->get_collection('data');

Inserting documents into MongoDB

In the next few lines we insert 3 documents. Each document is hash which is the translated into a BSON string.

$collection->insert_one({
    cpan => {
        name => 'Foo',
        version => 1,
    },
});

$collection->insert_one({
    cpan => {
        name => 'Foo',
        version => 2,
    },
});

$collection->insert_one({
    cpan => {
        name => 'Bar',
        version => 1,
    },
});

Fetching all the documents

Once we have the data in the database, we can use the find method on the collection without any parameters to fetch all the documents. find itself returns a MongoDB::Cursor object. On that we call the all method which, in LIST context, will return the documents along with the _id that was generated by MongoDB when we inserted the data structures. We can iterate over these documents and access the values and print them.

say '-----';
foreach my $e ($collection->find->all) {
    say "$e->{cpan}{name} $e->{cpan}{version}";
}

The output of this section of code is

-----
Foo 1
Foo 2
Bar 1

Finding documents base on an internal key-value pair

In the next example we use the find method again, but this time we send in a condition using the "dot notation". That means we are looking for documents that have a main key called 'cpan' which holds a hash in which there is an internal key called 'name' which has a value 'Foo',

say '-----';
foreach my $e ($collection->find({ 'cpan.name' => 'Foo' })->all) {
    say "$e->{cpan}{name} $e->{cpan}{version}";
}

The output of these few lines is:

-----
Foo 1
Foo 2

Delete document using deep condition

This call will find a document with the given condition and remove it from the database:

$collection->delete_one({ 'cpan.version' => 2 });

Confirm deletition

Then we repeat the previous call to find:

say '-----';
foreach my $e ($collection->find({ 'cpan.name' => 'Foo' })->all) {
    say "$e->{cpan}{name} $e->{cpan}{version}";
}

The output of this call proves that the delete_one call indeed removed a document:

-----
Foo 1

Delete MongoDB database using drop

Finally we call the drop method on the whole database to remove it from MongoDB. After all, we don't need the data from this example to stick around.

$database->drop;