MongoD...xamples(3pm)
π MongoDB::Examples(3pm) π
okay bestie, so this is a page from the User Contributed Perl Documentation β the manual name is MongoDB::Examples, and yeah, it lives in section 3pm like all your fave Perl module docs. It's called MongoDB::Examples and it's exactly what it sounds like: a whole vibe-check of MongoDB syntax with receipts. πΈ
β¨ NAME β¨
MongoDB::Examples β Some examples of MongoDB syntax π¦
Yeah that's it, that's the name. Short, iconic, doesn't over-explain. Main character energy fr. π
π VERSION π
version v2.2.2
π MAPPING SQL TO MONGODB π
okay so if you're a dev who's been living that SQL life and you're like "bestie how do I even say this in MongoDB" β this chart is literally for you. π
These are Perl-specific examples of translating SQL queries into MongoDB's query language. If you want the mappings for JavaScript (or honestly any other language), go peek at http://docs.mongodb.org/manual/reference/sql-comparison/. no cap. β¨
Quick housekeeping so nothing confuses you: in all the examples below, $db is a MongoDB::Database object that you got by calling "get_database". And if you wanna know more about the methods you see down there, go read MongoDB::MongoClient, MongoDB::Database and MongoDB::Collection. iykyk π«Ά
CREATE TABLE USERS (a Number, b Number)β Implicit, can be done explicitly.INSERT INTO USERS VALUES(1,1)
$db->get_collection( 'users' )->insert_one( { a => 1, b => 1 } );
SELECT a,b FROM users
$db->get_collection( 'users')->find( { } )->fields( { a => 1, b => 1 });
SELECT * FROM users
$db->get_collection( 'users' )->find;
SELECT * FROM users WHERE age=33
$db->get_collection( 'users' )->find( { age => 33 } )
SELECT a,b FROM users WHERE age=33
$db->get_collection( 'users' )->find( { age => 33 } )->fields( { a => 1, b => 1 });
SELECT * FROM users WHERE age=33 ORDER BY name
$db->get_collection( 'users' )->find( { age => 33 } )->sort( { name => 1 } );
SELECT * FROM users WHERE age>33
$db->get_collection( 'users' )->find( { age => { '$gt' => 33 } } );
SELECT * FROM users WHERE age<33
$db->get_collection( 'users' )->find( { age => { '$lt' => 33 } } );
SELECT * FROM users WHERE name LIKE "%Joe%"
$db->get_collection( 'users' )->find( { name => qr/Joe/ } );
SELECT * FROM users WHERE name LIKE "Joe%"
$db->get_collection( 'users' )->find( {name => qr/^Joe/ } );
SELECT * FROM users WHERE age>33 AND age<=40
$db->get_collection( 'users' )->find( { age => { '$gt' => 33, '$lte' => 40 } } );
SELECT * FROM users ORDER BY name DESC
$db->get_collection( 'users' )->find->sort( { name => -1 } );
CREATE INDEX myindexname ON users(name)
my $indexes = $db->get_collection( 'users' )->indexes;
$indexes->create_one( [ name => 1 ] );
CREATE INDEX myindexname ON users(name,ts DESC)
my $indexes = $db->get_collection( 'users' )->indexes;
$indexes->create_one( [ name => 1, ts => -1 ] );
SELECT * FROM users WHERE a=1 and b='q'
$db->get_collection( 'users' )->find( {a => 1, b => "q" } );
SELECT * FROM users LIMIT 10 SKIP 20
$db->get_collection( 'users' )->find->limit(10)->skip(20);
SELECT * FROM users WHERE a=1 or b=2
$db->get_collection( 'users' )->find( { '$or' => [ {a => 1 }, { b => 2 } ] } );
SELECT * FROM users LIMIT 1
$db->get_collection( 'users' )->find->limit(1);
EXPLAIN SELECT * FROM users WHERE z=3
$db->get_collection( 'users' )->find( { z => 3 } )->explain;
SELECT DISTINCT last_name FROM users
$db->get_collection( 'users' )->distinct( 'last_name' );
SELECT COUNT(*y) FROM users
$db->get_collection( 'users' )->count_documents;
SELECT COUNT(*y) FROM users where age > 30
$db->get_collection( 'users' )->count_documents( { "age" => { '$gt' => 30 } } );
SELECT COUNT(age) from users
$db->get_collection( 'users' )->count_documents( { age => { '$exists' => 1 } } );
UPDATE users SET a=1 WHERE b='q'
$db->get_collection( 'users' )->update_many( { b => "q" }, { '$set' => { a => 1 } } );
UPDATE users SET a=a+2 WHERE b='q'
$db->get_collection( 'users' )->update_many( { b => "q" }, { '$inc' => { a => 2 } } );
DELETE FROM users WHERE z="abc"
$db->get_database( 'users' )->delete_many( { z => "abc" } );
π₯ DATABASE COMMANDS π₯
okay so imagine you're in the MongoDB shell doing something cute and you're like "how do I say this in Perl tho". The best way? Run that function in the shell without parentheses β it'll literally print the source at you. Then you just translate that source into Perl, and honestly it's usually pretty easy. slay. π
β¨ for example β¨ β say we wanna use db.foo.validate in Perl. We run this in the shell:
> db.foo.validate
function (full) {
var cmd = {validate:this.getName()};
if (typeof full == "object") {
Object.extend(cmd, full);
} else {
cmd.full = full;
}
var res = this._db.runCommand(cmd);
if (typeof res.valid == "undefined") {
res.valid = false;
var raw = res.result || res.raw;
if (raw) {
var str = "-" + tojson(raw);
res.valid = !(str.match(/exception/) || str.match(/corrupt/));
var p = /lastExtentSize:(\d+)/;
var r = p.exec(str);
if (r) {
res.lastExtentSize = Number(r[1]);
}
}
}
return res;
}
and then boom, we take the important parts and translate them into Perl:
$db->run_command( [ validate => "foo" ] );
just like that. iconic. π¦
π Find-one-and-modify π
The find-one-and-modify commands in MongoDB::Collection are giving update (or remove) energy, but β plot twist β they'll also return the modified document. Super useful for implementing queues or locks, ngl. π
so here's the scenario: we've got a lil list of things to do, and we wanna grab the highest-priority item for processing and pop it off. We could do a find and then a delete_one, but bestieβ¦ that wouldn't be atomic π (a write could sneak in between the query and the remove, and that's a whole mess we don't need). Instead, use find_one_and_delete:
my $coll = $db->get_collection('todo');
my $next_task = $todo->find_one_and_delete(
{}, # empty filter means any document
{ sort => {priority => -1} },
);
and that will atomically find and pop the next-highest-priority task. no cap, it eats every time. π₯
wanna know more about find-and-modify? go read http://www.mongodb.org/display/DOCS/findAndModify+Command for all the details. β¨
heads up bestie: this is only part 1 π«Ά there's more where this came from, so don't go anywhere. β¨
β¨ AGGREGATION β¨
okay bestie, so the aggregation framework is MongoDB's glow-up version of SQL GROUP BY queries, but way more generic and way more powerful. An invocation of the aggregation framework specifies a series of stages in a pipeline to be executed in order by the server. Each stage of the pipeline is drawn from one of the following so-called "pipeline operators": $project, $match, $limit, $skip, $unwind, $group, $sort, and $geoNear. π
The aggregation framework is the preferred way of performing most aggregation tasks. New in version 2.2, it has largely obviated mapReduce (http://docs.mongodb.org/manual/reference/command/mapReduce/#dbcmd.mapReduce) and group (http://docs.mongodb.org/manual/reference/command/group/#dbcmd.group).
See the MongoDB aggregation framework documentation for more information (http://docs.mongodb.org/manual/aggregation/).
$match and $group π
The $group pipeline operator is used like GROUP BY in SQL. For example, suppose we have a number of local businesses stored in a "business" collection. If we wanted to find the number of coffeeshops in each neighborhood, we could do:
my $out = $db->get_collection('business')->aggregate(
[
{'$match' => {'type' => 'coffeeshop'}},
{'$group' => {'_id' => '$neighborhood', 'num_coffeshops' => {'$sum' => 1}}}
]
);
The SQL equivalent is "SELECT neighborhood, COUNT(*) FROM business GROUP BY neighborhood WHERE type = 'coffeeshop'". After executing the above aggregation query, $out will contain a MongoDB::QueryResult, allowing us to iterate through result documents such as the following:
(
{
'_id' => 'Soho',
'num_coffeshops' => 23
},
{
'_id' => 'Chinatown',
'num_coffeshops' => 14
},
{
'_id' => 'Upper East Side',
'num_coffeshops' => 10
},
{
'_id' => 'East Village',
'num_coffeshops' => 87
}
)
Note that aggregate takes an array reference as an argument. Each element of the array is a document which specifies a stage in the aggregation pipeline. Here our aggregation query consists of a $match phase followed by a $group phase. Use $match to filter the documents in the collection prior to aggregation. The "_id" field in the $group stage specifies the key to group by; the "$" in '$neighborhood' indicates that we are referencing the name of a key. Finally, we use the $sum operator to add one for every document in a particular neighborhood. There are other operators, such as $avg, $max, $min, $push, and $addToSet, which can be used in the $group phase and work much like $sum. π«Ά
$project and $unwind π¦
Now let's look at a more complex example of the aggregation framework that makes use of the $project and $unwind pipeline operators. Suppose we have a collection called 'courses' which contains information on college courses. An example document in the collection looks like this:
{
'_id' => 'CSCI0170',
'name' => 'Computer Science 17',
'description' => 'An Integrated Introduction to Computer Science',
'instructor_id' => 29823498,
'instructor_name' => 'A. Greenwald',
'students' => [
{ 'student_id' => 91736114, 'student_name' => 'D. Storch' },
{ 'student_id' => 89100891, 'student_name' => 'J. Rassi' }
]
}
We wish to generate a report containing one document per student that indicates the courses in which each student is enrolled. The following call to aggregate will do the trick:
my $out = $db->get_collection('courses')->aggregate([
{'$unwind' => '$students'},
{'$project' => {
'_id' => 0,
'course' => '$_id',
'student_id' => '$students.student_id',
}
},
{'$group' => {
'_id' => '$student_id',
'courses' => {'$addToSet' => '$course'}
}
}
]);
The output documents will each have a student ID number and an array of the courses in which that student is enrolled:
(
{
'_id' => 91736114,
'courses' => ['CSCI0170', 'CSCI0220', 'APMA1650', 'HIST1230']
},
{
'_id' => 89100891,
'courses' => ['CSCI0170', 'CSCI1670', 'CSCI1690']
}
)
The $unwind stage of the aggregation query "peels off" elements of the courses array one-by-one and places them in their own documents. After this phase completes, there is a separate document for each (course, student) pair. The $project stage then throws out unnecessary fields and keeps the ones we are interested in. It also pulls the student ID field out of its subdocument and creates a top-level field with the key "student_id". Last, we group by student ID, using $addToSet in order to add the unique courses for each student to the "courses" array. π
$sort, $skip, and $limit β¨
The $sort, $skip, and $limit pipeline operators work much like their companion methods in MongoDB::Cursor. Returning to the previous students and courses example, suppose that we were particularly interested in the student with the ID that is numerically third-to-highest. We could retrieve the course list for that student by adding $sort, $skip, and $limit phases to the pipeline:
my $out = $db->get_collection('courses')->aggregate([
{'$unwind' => '$students'},
{'$project' => {
'_id' => 0,
'course' => '$_id',
'student_id' => '$students.student_id',
}
},
{'$group' => {
'_id' => '$student_id',
'courses' => {'$addToSet' => '$course'}
}
},
{'$sort' => {'_id' => -1}},
{'$skip' => 2},
{'$limit' => 1}
]);
π QUERYING π
Nested Fields πͺΊ
MongoDB allows you to store deeply nested structures and then query for fields within them using dot-notation. For example, suppose we have a users collection with documents that look like:
{
"userId" => 12345,
"address" => {
"street" => "123 Main St",
"city" => "Springfield",
"state" => "MN",
"zip" => "43213"
}
}
If we want to query for all users from Springfield, we can do:
my $cursor = $users->find({"address.city" => "Springfield"});
This will search documents for an "address" field that is a subdocument and a "city" field within the subdocument. πΈ
βοΈ UPDATING βοΈ
Positional Operator π
In MongoDB 1.3.4 and later, you can use positional operator, "$", 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_one({"users.name" => "fred"}, {'users.$.name' => "george"});
This will update the array so that the element containing "name" => "fred" now has "name" => "george". π«
π AUTHORS π
David Golden <david@mongodb.com>Rassi <rassi@mongodb.com>Mike Friedman <friedo@friedo.com>Kristina Chodorow <k.chodorow@gmail.com>Florian Ragwitz <rafl@debian.org>
π COPYRIGHT AND LICENSE π
This software is Copyright (c) 2020 by MongoDB, Inc.
This is free software, licensed under:
The Apache License, Version 2.0, January 2004
and that's a wrap, bestie! This page came from perl v5.40.1, dated 2025-04-03, and it's the MongoD...xamples(3pm) manual. Slay responsibly. πβ¨
π¦ where this page comes from
- debian trixie: libmongodb-perl 2.2.2-3 Β· Apache-2.0
- ubuntu resolute: libmongodb-perl 2.2.2-3 Β· Apache-2.0
- ubuntu stonking: libmongodb-perl 2.2.2-3 Β· Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms