Mango(3pm)

πŸ“¦
version 1.30 Β· 3 versions
, in debian bookworm, debian trixie, ubuntu jammy, ubuntu noble, ubuntu resolute, ubuntu stonking

πŸ’– Mango πŸ’–

okay bestie, we're doing the Mango page today β€” it lives in the User Contributed Perl Documentation section of your manual, and it's genuinely one of the most iconic things in the Perl ecosystem. grab a snack, we're going in πŸ“


✨ NAME ✨

Mango β€” a Pure-Perl non-blocking I/O MongoDB driver πŸ’… no cap, that's the whole vibe.


🌸 SYNOPSIS 🌸

here's the whole thing, literally verbatim, because you're gonna want to copy-paste this:

use Mango;
use feature state;

# Declare a Mango helper
sub mango { state $m = Mango->new('mongodb://localhost:27017') }
# or in a Mojolicious::Lite app
helper mango => sub { state $m = Mango->new('mongodb://localhost:27017') };

# Insert document
my $oid   = mango->db('test')->collection('foo')->insert({bar => 'baz'});

# Find document
my $doc = mango->db('test')->collection('foo')->find_one({bar => 'baz'});
say $doc->{bar};

# Update document
mango->db('test')->collection('foo')
  ->update({bar => 'baz'}, {bar => 'yada'});

# Remove document
mango->db('test')->collection('foo')->remove({bar => 'yada'});

# Insert document with special BSON types
use Mango::BSON ':bson';
my $oid = mango->db('test')->collection('foo')
  ->insert({data => bson_bin("\x00\x01"), now => bson_time});

# Non-blocking concurrent find
my $delay = Mojo::IOLoop->delay(sub {
  my ($delay, @docs) = @_;
  ...
});
for my $name (qw(sri marty)) {
  my $end = $delay->begin(0);
  mango->db('test')->collection('users')->find({name => $name})->all(sub {
    my ($cursor, $err, $docs) = @_;
    $end->(@$docs);
  });
}
$delay->wait;

# Event loops such as AnyEvent are supported through EV
use EV;
use AnyEvent;
my $cv = AE::cv;
mango->db('test')->command(buildInfo => sub {
  my ($db, $err, $doc) = @_;
  $cv->send($doc->{version});
});
say $cv->recv;

look at that. it's giving effortless. 😌


πŸ¦‹ DESCRIPTION πŸ¦‹

so, Mango is a pure-Perl non-blocking I/O MongoDB driver β€” it's optimized for use with the Mojolicious real-time web framework, and it plays nice with multiple event loop support. super social, loves everyone.

but here's the tea: since MongoDB is still changing rapidly, only the latest stable version is supported. periodt. if you're clinging to the past and need MongoDB 2.6 support, you gotta use Mango 1.16. that's just the rules bestie πŸ’€

to actually learn more about MongoDB you should go look at the official documentation at <http://docs.mongodb.org> β€” the documentation included in this distribution is no replacement for it, like, at all. don't @ me.

for CRUD operations, look at Mango::Collection. πŸ‘‘

many arguments passed to methods, plus the values of attributes, get serialized to BSON with Mango::BSON, which hands you a bunch of helper functions so you can generate data types that Perl just doesn't have natively. all connections will be reset automatically if a new process has been forked, which means multiple processes can share the same Mango object safely. iconic behaviour honestly 🫢

and for better scalability (epoll, kqueue) plus to give you IPv6, SOCKS5 and TLS support, these optional modules will be used automatically if they're installed:

  • EV (4.0+)
  • IO::Socket::IP (0.20+)
  • IO::Socket::Socks (0.64+)
  • IO::Socket::SSL (1.84+)

and if you're feeling picky, individual features can be turned off with the MOJO_NO_IPV6, MOJO_NO_SOCKS and MOJO_NO_TLS environment variables. slay, you have options ✨


⭐ EVENTS ⭐

Mango inherits all events from Mojo::EventEmitter and can emit the following new ones. yes, new ones. a glow up πŸ’…

πŸ’« connection

$mango->on(connection => sub {
  my ($mango, $id) = @_;
  ...
});

emitted when a new connection has been established. it's the "hey bestie we're in" moment πŸŽ€


πŸ‘‘ ATTRIBUTES πŸ‘‘

Mango implements the following attributes. get comfy, there's a bunch.

πŸ’œ default_db

my $name = $mango->default_db;
$mango   = $mango->default_db('test');

the default database. defaults to "admin". lowkey the boss of databases.

πŸ’œ hosts

my $hosts = $mango->hosts;
$mango    = $mango->hosts([['localhost', 3000], ['localhost', 4000]]);

the servers to connect to. defaults to "localhost" and port 27017.

πŸ’œ inactivity_timeout

my $timeout = $mango->inactivity_timeout;
$mango      = $mango->inactivity_timeout(15);

the maximum amount of time in seconds a connection can be inactive before it gets closed. defaults to 0. and setting the value to 0 will allow connections to be inactive indefinitely β€” yes, forever, no cap.

πŸ’œ ioloop

my $loop = $mango->ioloop;
$mango   = $mango->ioloop(Mojo::IOLoop->new);

the event loop object to use for blocking I/O operations. defaults to a Mojo::IOLoop object.

πŸ’œ j

my $j  = $mango->j;
$mango = $mango->j(1);

wait for all operations to have reached the journal. defaults to 0.

πŸ’œ max_bson_size

my $max = $mango->max_bson_size;
$mango  = $mango->max_bson_size(16777216);

the maximum size for BSON documents in bytes. defaults to 16777216 (that's 16MB bestie, huge).

πŸ’œ max_connections

my $max = $mango->max_connections;
$mango  = $mango->max_connections(5);

the maximum number of connections to use for non-blocking operations. defaults to 5.

πŸ’œ max_write_batch_size

my $max = $mango->max_write_batch_size;
$mango  = $mango->max_write_batch_size(1000);

the maximum number of write operations to batch together. defaults to 1000.

πŸ’œ protocol

my $protocol = $mango->protocol;
$mango       = $mango->protocol(Mango::Protocol->new);

the protocol handler. defaults to a Mango::Protocol object.

πŸ’œ w

my $w  = $mango->w;
$mango = $mango->w(2);

wait for all operations to have reached at least this many servers. 1 indicates just primary, 2 indicates primary and at least one secondary. defaults to 1.

πŸ’œ wtimeout

my $timeout = $mango->wtimeout;
$mango      = $mango->wtimeout(1);

timeout for write propagation in milliseconds. defaults to 1000.


πŸŽ€ METHODS πŸŽ€

Mango inherits all methods from Mojo::Base and implements the following new ones. the way that this class just *keeps giving*… 😭

🌸 backlog

my $num = $mango->backlog;

the number of queued operations that have not yet been assigned to a connection. the little waiting room 🫢

🌸 db

my $db = $mango->db;
my $db = $mango->db('test');

build a Mango::Database object for a database. uses "default_db" if no name is provided.

⚠️ okay listen: note that the reference "mango" in Mango::Database is weakened, so the Mango object needs to be referenced elsewhere as well. don't let it float away bestie, it will literally evaporate πŸ’€

🌸 from_string

$mango
  = $mango->from_string('mongodb://sri:s3cret@localhost:3000/test?w=2');

parse configuration from a connection string. cute and functional ✨

🌸 get_more

my $reply = $mango->get_more($namespace, $return, $cursor);

perform a low level "GET_MORE" operation. you can also append a callback to perform the operation non-blocking:

$mango->get_more(($namespace, $return, $cursor) => sub {
  my ($mango, $err, $reply) = @_;
  ...
});
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;

🌸 kill_cursors

$mango->kill_cursors(@ids);

perform a low level "KILL_CURSORS" operation. you can also append a callback to perform the operation non-blocking:

$mango->kill_cursors(@ids => sub {
  my ($mango, $err) = @_;
  ...
});
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;

🌸 new

my $mango = Mango->new;
my $mango = Mango->new('mongodb://sri:s3cret@localhost:3000/test?w=2');

# Using TLS encryption
my $mango = Mango->new('mongodb://127.0.0.1:27017', tls => 1,
  tls_cert => '/path/to/certificate.pem');

construct a new Mango object, and parse the connection string with "from_string" if that's needed. πŸ’…

🚨 okay this one's important, bestie: it is strongly recommended to build your Mango object inside a helper function like the one shown in the synopsis. why? because the Mango's object reference inside Mango::Database objects is weakened to avoid memory leaks. this means your Mango instance is quickly going to get undefined after you use the "db" method. so use a helper to prevent that. i'm literally begging you πŸ™ˆ

if a username and a password are provided, Mango will try to authenticate using SCRAM-SHA1.

⚠️ Warning: this will require Authen::SCRAM, which is not installed by default.

any extra arguments given after the connection string will be passed to the "connect" method from Mojo::IOLoop::Client. to connect to a server using TLS, use the options "tls" (boolean), "tls_cert" and optionally "tls_ca". πŸ”

🌸 query

my $reply
  = $mango->query($namespace, $flags, $skip, $return, $query, $fields);

perform a low level "QUERY" operation. you can also append a callback to perform the operation non-blocking:

$mango->query(($namespace, $flags, $skip, $return, $query, $fields) => sub {
  my ($mango, $err, $reply) = @_;
  ...
});
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;

🧚 DEBUGGING 🧚

you can set the MANGO_DEBUG environment variable to get some advanced diagnostics information printed to STDERR. it's giving detective mode πŸ”

MANGO_DEBUG=1

πŸ’œ SPONSORS πŸ’œ

some of the work on this distribution has been sponsored by Drip Depot <http://www.dripdepot.com>. thank you!! 🫢 they ate, honestly.


🌈 AUTHOR 🌈

Sebastian Riedel, "sri@cpan.org".

current maintainer: Olivier Duclos "odc@cpan.org". πŸ‘‘


⭐ CREDITS ⭐

in alphabetical order, no favourites here:

  • alexbyk
  • Andrey Khozov
  • Colin Cyr

Copyright (C) 2013-2014, Sebastian Riedel.

this program is free software, you can redistribute it and/or modify it under the terms of the Artistic License version 2.0. periodt ✨


πŸ¦‹ SEE ALSO πŸ¦‹


and that's the whole page bestie πŸ’– this was pulled from the perl v5.30.3 manual, dated 2020-06-05 β€” so if you're reading this way later, hi, hope you're hydrated πŸ“ go build something iconic with it. mwah πŸ«ΆπŸ‘‘