MongoDB has a fun feature called aggregation. There's two ways of doing it, aggregation pipelines and map-reduce. Map-reduce is exactly what you'd expect if you're from a functional programming background: you provide MongoDB a map function that it will run every item in the array and then a reduce function to aggregate your collection into a smaller set of data.
MongoDB also has a concept of aggregation pipelines that tend to perform better and can also be easier to maintain. With these you provide a configuration object to the aggregation pipeline
What if we wanted to know how many puppies, adult, and senior dogs we have in our pets collection? Let's try just that
db.pets.aggregate([
{
$bucket: {
groupBy: "$age",
boundaries: [0, 3, 9, 15],
default: "very senior",
output: {
count: { $sum: 1 },
},
},
},
]);
- With the aggregation pipelines, you provide a step of things to do. In this case we only have one step, bucket pets into 0-2 years old, 3-8 years old, 9-14 years (the last boundary is exclusive, so 15 is not included), and "very senior" (which is the default bucket.)
- With the output you're defining what you want to pass to the next step. In this case we just want to sum them up by adding 1 to the count each time we see a pet that matches a bucket.
This is all pets. We want just dogs. Let's add another stage.
db.pets.aggregate([
{
$match: {
type: "dog",
},
},
{
$bucket: {
groupBy: "$age",
boundaries: [0, 3, 9, 15],
default: "very senior",
output: {
count: { $sum: 1 },
},
},
},
]);
Using the $match stage of the aggregation, we can exclude every pet that isn't a dog.
Last one, what if we wanted to sort the results by which group had the most pets?
db.pets.aggregate([
{
$match: {
type: "dog",
},
},
{
$bucket: {
groupBy: "$age",
boundaries: [0, 3, 9, 15],
default: "very senior",
output: {
count: { $sum: 1 },
},
},
},
{
$sort: {
count: -1,
},
},
]);
As you can see, you just add more stages to the aggregation until you gather the insights you're looking for. There are many more things you can do, so here's a link to all the existing aggregation stages.
This is definitely one of the most fun parts about MongoDB. I used to use MongoDB's aggregation features to catch fraudsters in our classifieds app!