MongoDB Aggregation

In MongoDB, aggregation is mainly used to process data (such as calculating averages, sums, etc.) and return the computed results.

somewhat similar toSQLin the SQL statementcount(*)。


aggregate() method

The aggregation method in MongoDB uses aggregate().

Syntax

The basic syntax format of the aggregate() method is as follows:

>db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)

Example

The data in the collection is as follows:

{
   _id: ObjectId(7df78ad8902c)
   title: 'MongoDB Overview', 
   description: 'MongoDB is no sql database',
   by_user: 'example.com',
   url: 'http://www.example.com',
   tags: ['mongodb', 'database', 'NoSQL'],
   likes: 100
},
{
   _id: ObjectId(7df78ad8902d)
   title: 'NoSQL Overview', 
   description: 'No sql database is very fast',
   by_user: 'example.com',
   url: 'http://www.example.com',
   tags: ['mongodb', 'database', 'NoSQL'],
   likes: 10
},
{
   _id: ObjectId(7df78ad8902e)
   title: 'Neo4j Overview', 
   description: 'Neo4j is no sql database',
   by_user: 'Neo4j',
   url: 'http://www.neo4j.com',
   tags: ['neo4j', 'database', 'NoSQL'],
   likes: 750
},

Now let's use the above collection to calculate the number of articles written by each author. The result of using aggregate() is as follows:

> db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])
{
   "result" : [
      {
         "_id" : "example.com",
         "num_tutorial" : 2
      },
      {
         "_id" : "Neo4j",
         "num_tutorial" : 1
      }
   ],
   "ok" : 1
}
>

The above example is similar to the SQL statement:

 select by_user, count(*) from mycol group by by_user

In the above example, we group the data by the by_user field and calculate the sum of the same values in the by_user field.

The following table shows some aggregation expressions:

ExpressionDescriptionExample
$sumCalculates the sum.db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}])
$avgCalculates the averagedb.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}])
$minGets the minimum value corresponding to all documents in the collection.db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}])
$maxGets the maximum value corresponding to all documents in the collection.db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}])
$pushAdds values to an array without checking for duplicate values.db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}])
$addToSetAdds values to an array, checking for duplicates; if the same value already exists in the array, it is not added.db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}])
$firstGets the first document data according to the sorting of the source documents.db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}])
$lastGets the last document data according to the sorting of the source documents.db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}])

Pipeline Concept

In Unix and Linux, pipelines are generally used to take the output of the current command as the argument for the next command.

MongoDB's aggregation pipeline processes MongoDB documents in one pipeline stage and then passes the results to the next pipeline stage. Pipeline operations can be repeated.

Expression: Processes input documents and outputs results. Expressions are stateless and can only be used to compute documents in the current aggregation pipeline; they cannot process other documents.

Here we introduce several commonly used operations in the aggregation framework:

  • $project: Modifies the structure of the input document. It can be used to rename, add, or remove fields, as well as to create computed results and nested documents.
  • $match: Used to filter data and only output documents that meet the conditions. $match uses MongoDB's standard query operations.
  • $limit: Used to limit the number of documents returned by the MongoDB aggregation pipeline.
  • $skip: Skips a specified number of documents in the aggregation pipeline and returns the remaining documents.
  • $unwind: Splits an array-type field in a document into multiple documents, each containing one value from the array.
  • $group: Groups documents in a collection, which can be used for statistical results.
  • $sort: Sorts the input documents and outputs them.
  • $geoNear: Outputs ordered documents that are near a certain geographic location.

Pipeline Operator Examples

1. $project example

db.article.aggregate(
    { $project : {
        title : 1 ,
        author : 1 ,
    }}
 );

In this way, the result only contains the three fields: _id, tilte, and author. By default, the _id field is included. If you don't want to include _id, you can do this:

db.article.aggregate(
    { $project : {
        _id : 0 ,
        title : 1 ,
        author : 1
    }});

2. $match example

db.articles.aggregate( [
                        { $match : { score : { $gt : 70, $lte : 90 } } },
                        { $group: { _id: null, count: { $sum: 1 } } }
                       ] );

$match is used to get records with scores greater than 70 and less than or equal to 90, and then send the matching records to the next stage, the $group pipeline operator, for processing.

3. $skip example

db.article.aggregate(
    { $skip : 5 });

After processing by the $skip pipeline operator, the first five documents are "filtered" out.

Other extensions