The Aggregation Framework

45
Aggregation Framework Senior Solutions Architect, MongoDB Norberto Leite #mongodbdays @nleite #aggfwk

description

MongoDB offers two native data processing tools: MapReduce and the Aggregation Framework. MongoDB’s built-in aggregation framework is a powerful tool for performing analytics and statistical analysis in real-time and generating pre-aggregated reports for dashboarding. In this session, we will demonstrate how to use the aggregation framework for different types of data processing including ad-hoc queries, pre-aggregated reports, and more. At the end of this talk, you should walk aways with a greater understanding of the built-in data processing options in MongoDB and how to use the aggregation framework in your next project.

Transcript of The Aggregation Framework

Page 1: The Aggregation Framework

Aggregation Framework

Senior Solutions Architect, MongoDB

Norberto Leite

#mongodbdays @nleite #aggfwk

Page 2: The Aggregation Framework

Agenda

• What is the Aggregation Framework?

• The Aggregation Pipeline

• Usage and Limitations

• Aggregation and Sharding

• Summary

Page 3: The Aggregation Framework

What is the Aggregation Framework?

Page 4: The Aggregation Framework

Aggregation Framework

Page 5: The Aggregation Framework

Aggregation in Nutshell

• We're storing our data in MongoDB

• Our applications need to run ad-hoc queries for grouping, summarizations, reporting, etc.

• We must have a way to reshape data easily to support these access patterns

• You can use Aggregation Framework for this!

Page 6: The Aggregation Framework

• Extremely versatile, powerful

• Overkill for simple aggregation tasks

• Averages• Summation• Grouping• Reshaping

MapReduce is great, but…

• High level of complexity

• Difficult to program and debug

Page 7: The Aggregation Framework

Aggregation Framework

• Plays nice with sharding

• Executes in native code– Written in C++– JSON parameters

• Flexible, functional, and simple– Operation pipeline– Computational expressions

Page 8: The Aggregation Framework

Aggregation Pipeline

Page 9: The Aggregation Framework

Pipeline

Page 10: The Aggregation Framework

What is an Aggregation Pipeline?• A Series of Document Transformations

– Executed in stages– Original input is a collection– Output as a cursor or a collection

• Rich Library of Functions– Filter, compute, group, and summarize data– Output of one stage sent to input of next– Operations executed in sequential order

$match

$project $group $sort

Page 11: The Aggregation Framework

Pipeline Operators

• $sort• Order documents

• $limit / $skip• Paginate documents

• $redact• Restrict documents

• $geoNear• Proximity sort

documents

• $let, $map• Define variables

• $match• Filter documents

• $project• Reshape documents

• $group• Summarize

documents

• $unwind• Expand documents

Page 12: The Aggregation Framework

{

"_id" : ObjectId("54523d2d25784427c6fabce1"),

"From" : "[email protected]",

"To" : "[email protected]",

"Date" : ISODate("2012-08-15T22:32:34Z"),

"body" : {

"text/plain" : ”Hello Munich, nice to see yalll!"

},

"Subject" : ”Live From MongoDB World"

}

Our Example Data

Page 13: The Aggregation Framework

$match

• Filter documents– Uses existing query syntax– No $where (server side

Javascript)

Page 14: The Aggregation Framework

Matching Field Values

{ subject: "Hello There", words: 218, from: "[email protected]"}

{ $match: { from: "[email protected]"}}

{ subject: "I love Hofbrauhaus", words: 90, from: "[email protected]"}{ subject: "MongoDB Rules!", words: 100, from: "[email protected]"}

{ subject: "MongoDB Rules!", words: 100, from: "[email protected]"}

Page 15: The Aggregation Framework

Matching with Query Operators

{ subject: "Hello There", words: 218, from: "[email protected]"}

{ $match: { words: {$gt: 100} }}

{ subject: "I love Hofbrauhaus", words: 90, from: "[email protected]"}{ subject: "MongoDB Rules!", words: 100, from: "[email protected]"}

{ subject: "MongoDB Rules!", words: 100, from: "[email protected]"}

{ subject: "Hello There", words: 218, from: "[email protected]"}

Page 16: The Aggregation Framework

$project

• Reshape Documents– Include, exclude or rename

fields– Inject computed fields– Create sub-document fields

Page 17: The Aggregation Framework

Including and Excluding Fields

{ _id: 12345, subject: "Hello There", words: 218, from:"[email protected]" to: [ "[email protected]", "[email protected]" ], account: "mongodb mail", date: ISODate("2012-08-05"), replies: 3, folder: "Inbox", ...}

{ $project: { _id: 0, subject: 1, from: 1}}

{ subject: "Hello There", from:"[email protected]"}

Page 18: The Aggregation Framework

Including and Excluding Fields

{ _id: 12345, subject: "Hello There", words: 218, from:"[email protected]" to: [ "[email protected]", "[email protected]" ], account: "mongodb mail", date: ISODate("2012-08-05"), replies: 3, folder: "Inbox", ...}

{ $project: { _id: 0, subject: 1, from: 1}}

{ subject: "Hello There", from:"[email protected]"}

Page 19: The Aggregation Framework

Renaming and Computing Fields

{ $project: { spamIndex: { $mul: ["$words", "$replies"] }, user: "$from"}}

{ _id: 12345, spamIndex: 72.6666 , user: "[email protected]"}

{ _id: 12345, subject: "Hello There", words: 218, from:"[email protected]" to: [ "[email protected]", "[email protected]" ], account: "mongodb mail", date: ISODate("2012-08-05"), replies: 3, folder: "Inbox", ...}

Page 20: The Aggregation Framework

Creating Sub-Document Fields

{ $project: { subject: 1, stats: { replies: "$replies", from: "$from", date: "$date" }}}

{ _id: 375, subject: "Hello There", stats: { replies: 3, from: "[email protected]", date: ISODate("2012-08-05") }}

{ _id: 12345, subject: "Hello There", words: 218, from:"[email protected]" to: [ "[email protected]", "[email protected]" ], account: "mongodb mail", date: ISODate("2012-08-05"), replies: 3, folder: "Inbox", ...}

Page 21: The Aggregation Framework

$group• Group documents by value

– Field reference, object, constant

– Other output fields are computed• $max, $min, $avg, $sum• $addToSet, $push• $first, $last

– Processes all data in memory by default

Page 22: The Aggregation Framework

Calculating An Average

{ $group: { _id: "$from", avgWords: { $avg: "$words" }}}

{ _id: "[email protected]", avgPages: 154}

{ _id: "[email protected]", avgPages: 100}

{ subject: "Hello There", words: 218, from: "[email protected]"}

{ subject: "I love Hofbrauhaus", words: 90, from: "[email protected]"}{ subject: "MongoDB Rules!", words: 100, from: "[email protected]"}

Page 23: The Aggregation Framework

Summing Fields and Counting

{ $group: { _id: "$from", words: { $sum: "$words" }, mails: { $sum: 1 }}}

{ _id: "[email protected]", words: 308, mails: 2}{ _id: "[email protected]", words: 100, mails: 1}

{ subject: "Hello There", words: 218, from: "[email protected]"}

{ subject: "I love Hofbrauhaus", words: 90, from: "[email protected]"}{ subject: "MongoDB Rules!", words: 100, from: "[email protected]"}

Page 24: The Aggregation Framework

$unwind

• Operate on an array field– Create documents from array

elements• Array replaced by element value• Missing/empty fields → no output• Non-array fields → error

– Pipe to $group to aggregate

Page 25: The Aggregation Framework

Collecting Distinct Values

{ subject: "2.8 will be great!", to: "[email protected]", account : "mongodb mail” }

{ $unwind: "$to" }{ _id: 2222, subject: "2.8 will be great!", to: [ "[email protected]",

"[email protected]", "[email protected]", ], account: "mongodb mail"}

{ subject: "2.8 will be great!", to: "[email protected]", account : "mongodb mail” }{ subject: "2.8 will be great!", to: "[email protected]", account : "mongodb mail” }

Page 26: The Aggregation Framework

$sort, $limit, $skip

• Sort documents by one or more fields– Same order syntax as cursors– Waits for earlier pipeline operator to

return– In-memory unless early and indexed

• Limit and skip follow cursor behavior

Page 27: The Aggregation Framework

$redact

• Restrict access to Documents– Use document fields to define

privileges– Apply conditional queries to validate

users

• Field Level Access Control– $$DESCEND, $$PRUNE, $$KEEP– Applies to root and subdocument

fields

Page 28: The Aggregation Framework

{

_id: 375,

item: "Sony XBR55X900A 55Inch 4K Ultra High Definition TV",

Manufacturer: "Sony",

security: 0,

quantity: 12,

list: 4999,

pricing: {

security: 1,

sale: 2698,

wholesale: {

security: 2,

amount: 2300 }

}

}

$redact Example Data

Page 29: The Aggregation Framework

Query by Security Level

security = 0

db.catalog.aggregate([ { $match: {item: /^.*XBR55X900A*/}}, { $redact: { $cond: { if: { $lte: [ "$security", ?? ] }, then: "$$DESCEND", else: "$$PRUNE" } }}])

{ "_id" : 375, "item" : "Sony XBR55X900A 55Inch 4K Ultra High Definition TV", "Manufacturer" : "Sony”, "security" : 0, "quantity" : 12, "list" : 4999}

{"_id" : 375,"item" : "Sony XBR55X900A 55Inch 4K Ultra

High Definition TV","Manufacturer" : "Sony","security" : 0,"quantity" : 12,"list" : 4999,"pricing" : {

"security" : 1,"sale" : 2698,"wholesale" : {

"security" : 2,"amount" : 2300

}}

}

security = 2

Page 30: The Aggregation Framework

$geoNear

• Order/Filter Documents by Location– Requires a geospatial index– Output includes physical distance– Must be first aggregation stage

Page 31: The Aggregation Framework

{

"_id" : 35089,

"city" : “Sony”,

"loc" : [

-86.048397,

32.979068

],

"pop" : 1584,

"state" : "AL”

}

$geonear Example Data

Page 32: The Aggregation Framework

Query by Proximity

db.catalog.aggregate([ { $geoNear : { near: [ -86.000, 33.000 ], distanceField: "dist", maxDistance: .050, spherical: true, num: 3 }}])

{"_id" : "35089","city" : "KELLYTON","loc" : [ -86.048397,

32.979068 ],"pop" : 1584,"state" : "AL","dist" :

0.0007971432165364155},{

"_id" : "35010","city" : "NEW SITE","loc" : [ -85.951086,

32.941445 ],"pop" : 19942,"state" : "AL","dist" :

0.0012479615347306806},{

"_id" : "35072","city" : "GOODWATER","loc" : [ -86.078149,

33.074642 ],"pop" : 3813,"state" : "AL","dist" :

0.0017333719627032555}

Page 33: The Aggregation Framework

Usage and Limitations

Page 34: The Aggregation Framework

Usage

• collection.aggregate([…], {<options>})– Returns a cursor– Takes an optional document to specify aggregation

options• allowDiskUse, explain

– Use $out to send results to a Collection

• db.runCommand({aggregate:<collection>, pipeline:[…]})– Returns a document, limited to 16 MB

Page 35: The Aggregation Framework

Collection

db.books.aggregate([

{ $project: { language: 1 }},

{ $group: { _id: "$language", numTitles: { $sum: 1 }}}

])

{ _id: "Russian", numTitles: 1 },{ _id: "English", numTitles: 2 }

Page 36: The Aggregation Framework

Database Command

db.runCommand({ aggregate: "books", pipeline: [ { $project: { language: 1 }}, { $group: { _id: "$language", numTitles: { $sum: 1 }}} ]})

{result : [

{ _id: "Russian", numTitles: 1 },{ _id: "English", numTitles: 2 }

],“ok” : 1

}

Page 37: The Aggregation Framework

Limitations

• Pipeline operator memory limits– Stages limited to 100 MB– Use “allowDiskUse” option to use disk for larger

data sets

• Some BSON types unsupported– Symbol, MinKey, MaxKey, DBRef, Code, and

CodeWScope

Page 38: The Aggregation Framework

Aggregation and Sharding

Page 39: The Aggregation Framework

Sharding

Result

mongos

Shard 1 (Primary)$match, $project, $group

Shard 2$match, $project, $group

Shard 3

excluded

Shard 4$match, $project, $group

• Workload split between shards– Shards execute pipeline up to a

point– Primary shard merges cursors and

continues processing*– Use explain to analyze pipeline split– Early $match may excuse shards– Potential CPU and memory

implications for primary shard host

* Prior to v2.6 second stage pipeline processing was done by mongos

Page 40: The Aggregation Framework

Summary

Page 41: The Aggregation Framework

Framework Use Cases

• Basic aggregation queries

• Ad-hoc reporting

• Real-time analytics

• Visualizing and reshaping data

Page 42: The Aggregation Framework

Extending the Framework

• Adding new pipeline operators, expressions

• $out and $tee for output control– https://jira.mongodb.org/browse/SERVER-3253

Page 43: The Aggregation Framework

Future Enhancements

• Automatically move $match earlier if possible

• Pipeline explain facility

• Memory usage improvements– Grouping input sorted by _id– Sorting with limited output

Page 44: The Aggregation Framework

Enabling Developers

• Doing more within MongoDB, faster

• Refactoring MapReduce and groupings– Replace pages of JavaScript– Longer aggregation pipelines

• Quick aggregations from the shell

Page 45: The Aggregation Framework

Obrigado!

SA | Eng – [email protected]

Norberto Leite

#mongodbdays #aggfwk #devs @mongodb