$function (aggregation) (original) (raw)

$function

Important

Server-side JavaScript Deprecated

Starting in MongoDB 8.0, server-side JavaScript functions ($accumulator, $function, $where) are deprecated. MongoDB logs a warning when you run these functions.

Defines a custom aggregation function or expression in JavaScript.

You can use the $function operator to define custom functions to implement behavior not supported by the MongoDB Query Language. See also $accumulator.

Important

Executing JavaScript inside an aggregation expression may decrease performance. Only use the $functionoperator if the provided pipeline operators cannot fulfill your application's needs.

The $function operator has the following syntax:


{

  $function: {

    body: <code>,

    args: <array expression>,

    lang: "js"

  }

}

Field Type Description
body String or Code The function definition. You can specify the function definition as either BSON type Code or String. See alsolang.function(arg1, arg2, ...) { ... }or"function(arg1, arg2, ...) { ... }"
args Array Arguments passed to the function body. If the body function does not take an argument, you can specify an empty array [ ].The array elements can be any BSON type, including Code. SeeExample 2: Alternative to $where.
lang String The language used in the body. You must specify lang: "js".

You cannot use $function as part of a schema validation query predicate.

To use $function, you must have server-side scripting enabled (default).

If you do not use $function (or $accumulator,$where, or mapReduce), disable server-side scripting:

See also ➤ Run MongoDB with Secure Configuration Options.

The query operator $where can also be used to specify JavaScript expression. However:

Given the available aggregation operators:

MongoDB 6.0 upgrades the internal JavaScript engine used forserver-side JavaScript,$accumulator, $function, and $whereexpressions and from MozJS-60 to MozJS-91. Several deprecated, non-standard array and string functions that existed in MozJS-60 are removed in MozJS-91.

For the complete list of removed array and string functions, see the6.0 compatibility notes.

Create a sample collection named players with the following documents:


db.players.insertMany([

   { _id: 1, name: "Miss Cheevous",  scores: [ 10, 5, 10 ] },

   { _id: 2, name: "Miss Ann Thrope", scores: [ 10, 10, 10 ] },

   { _id: 3, name: "Mrs. Eppie Delta ", scores: [ 9, 8, 8 ] }

])

The following aggregation operation uses $addFields to add new fields to each document:


db.players.aggregate( [

   { $addFields:

      {

        isFound:

            { $function:

               {

                  body: function(name) {

                     return hex_md5(name) == "15b0a220baa16331e8d80e15367677ad"

                  },

                  args: [ "$name" ],

                  lang: "js"

               }

            },

         message:

            { $function:

               {

                  body: function(name, scores) {

                     let total = Array.sum(scores);

                     return `Hello <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi>n</mi><mi>a</mi><mi>m</mi><mi>e</mi></mrow><mi mathvariant="normal">.</mi><mi>Y</mi><mi>o</mi><mi>u</mi><mi>r</mi><mi>t</mi><mi>o</mi><mi>t</mi><mi>a</mi><mi>l</mi><mi>s</mi><mi>c</mi><mi>o</mi><mi>r</mi><mi>e</mi><mi>i</mi><mi>s</mi></mrow><annotation encoding="application/x-tex">{name}.  Your total score is </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathnormal">nam</span><span class="mord mathnormal">e</span></span><span class="mord">.</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mord mathnormal">o</span><span class="mord mathnormal">u</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal">t</span><span class="mord mathnormal">o</span><span class="mord mathnormal">t</span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">score</span><span class="mord mathnormal">i</span><span class="mord mathnormal">s</span></span></span></span>{total}.`

                  },

                  args: [ "$name", "$scores"],

                  lang: "js"

               }

            }

       }

    }

] )

The operation returns the following documents:


{ "_id" : 1, "name" : "Miss Cheevous", "scores" : [ 10, 5, 10 ], "isFound" : false, "message" : "Hello Miss Cheevous.  Your total score is 25." }

{ "_id" : 2, "name" : "Miss Ann Thrope", "scores" : [ 10, 10, 10 ], "isFound" : true, "message" : "Hello Miss Ann Thrope.  Your total score is 30." }

{ "_id" : 3, "name" : "Mrs. Eppie Delta ", "scores" : [ 9, 8, 8 ], "isFound" : false, "message" : "Hello Mrs. Eppie Delta .  Your total score is 25." }

Note

Aggregation Alternatives Preferred over $where

The $expr operator allows the use ofaggregation expressions within the query language. And the $function and $accumulatorallows users to define custom aggregation expressions in JavaScript if the provided pipeline operators cannot fulfill your application's needs.

Given the available aggregation operators:

As an alternative to a query that uses the $where operator, you can use $expr and $function. For example, consider the following $where example.


db.players.find( { $where: function() {

   return (hex_md5(this.name) == "15b0a220baa16331e8d80e15367677ad")

} } );

The db.collection.find() operation returns the following document:


{ "_id" : 2, "name" : "Miss Ann Thrope", "scores" : [ 10, 10, 10 ] }

The example can be expressed using $expr and $function:


db.players.find( {$expr: { $function: {

      body: function(name) { return hex_md5(name) == "15b0a220baa16331e8d80e15367677ad"; },

      args: [ "$name" ],

      lang: "js"

} } } )