Use custom aggregation expression operator ($accumulator) in MongoDB aggregation pipeline

The custom aggregate expression operator mainly completes more complex aggregate query operations by customizing some Javascript functions; in this article, we mainly introduce the use of $accumulator :

1. Preparation

Initialize course grade data

db.subjectScores.insertMany([
    { "_id": 1, "name": "张三", "subject": "eng", "score": 80 },
    { "_id": 2, "name": "李四", "subject": "eng", "score": 60 },
    { "_id": 3, "name": "王五", "subject": "eng", "score": 90 },
    { "_id": 4, "name": "张三", "subject": "math", "score": 70 },
    { "_id": 5, "name": "李四", "subject": "math", "score": 90 },
    { "_id": 6, "name": "王五", "subject": "math", "score": 50 },
    { "_id": 7, "name": "张三", "subject": "physics", "score": 80 },
    { "_id": 8, "name": "李四", "subject": "physics", "score": 60 },
    { "_id": 9, "name": "王五", "subject": "physics", "score": 70 }
])

Two, $accumulator

grammar:

{
  $accumulator: {
    init: <code>,
    initArgs: <array expression>,        // Optional
    accumulate: <code>,
    accumulateArgs: <array expression>,
    merge: <code>,
    finalize: <code>,                    // Optional
    lang: <string>
  }
}

init: The function is used to initialize the state object and receive parameters from initArgs

function (<initArg1>, <initArg2>, ...) {
  ...
  return <initialState>
}

initArgs: optional, list of initialization parameters

[ <initArg1>, <initArg2>, ... ]

accumulate: The function is used to accumulate documents, the first parameter is the state object, other parameters are received from accumulateArgs; returns a new state object

function(state, <accumArg1>, <accumArg2>, ...) {
  ...
  return <newState>
}

accumulateArgs: list of accumulated arguments

[ <accumArg1>, <accumArg2>, ... ]

merge: The function is used to merge two state objects; returns a new state object

function (<state1>, <state2>) {
  <logic to merge state1 and state2>
  return <newState>
}

finalize: The function is used to return the aggregation result

function (state) {
  ...
  return <finalState>
}

lang: the language used, currently only supports js

$accumulator can only be used in 4.4 and later versions

3. Example: Calculate the total score of the students

Aggregation queries are as follows:

db.subjectScores.aggregate([
    {
        $group: {
            "_id": "$name",
            "score": {
                $accumulator: {
                    init: function() {
                        return {
                            sum: 0
                        }
                    },
                    accumulate: function(state, score) {
                        return {
                            sum: state.sum + score
                        }
                    },
                    accumulateArgs: [ "$score" ],
                    merge: function(state1, state2) {
                        return {
                            sum: state1.sum + state2.sum
                        }
                    },
                    finalize: function(state) {
                        return state.sum
                    },
                    lang: "js"
                }
            }
        }
    }
])

 We explain the aggregation query above:

1. Group course grade documents by name

2. Initialize the state object and accumulate and sum the scores in the input documents

3. Merge state objects

4. Return the sum value in the state object as the total score

The aggregation query above is equivalent to:

db.subjectScores.aggregate([
    {
        $group: {
            "_id": "$name",
            "score": { $sum: "$score" }
        }
    }
])

The results of the aggregation query are as follows:

{ "_id" : "王五", "score" : 210 }
{ "_id" : "李四", "score" : 210 }
{ "_id" : "张三", "score" : 230 }

Guess you like

Origin blog.csdn.net/m1729339749/article/details/130595027