$function (aggregation)
On this page
Definition
$functionNew in version 4.4.
Defines a custom aggregation function or expression in JavaScript.
You can use the
$functionoperator 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.
Syntax
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 also lang.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. See Example 2: Alternative to $where.
|
| lang | String | The language used in the body. You must specify lang: "js".
|
Considerations
Schema Validation Restriction
You cannot use $function as part of schema validation query expression.
Javascript Enablement
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:
-
For a
mongodinstance, seesecurity.javascriptEnabledconfiguration option or--noscriptingcommand-line option. -
For a
mongosinstance, seesecurity.javascriptEnabledconfiguration option or the--noscriptingcommand-line option starting in MongoDB 4.4.In earlier versions, MongoDB does not allow JavaScript execution onmongosinstances.
Alternative to $where
The query operator $where can also be used to specify JavaScript expression. However:
-
The
$exproperator allows the use of aggregation expressions within the query language. -
Starting in MongoDB 4.4, the
$functionand$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:
-
The use of
$exprwith aggregation operators that do not use JavaScript (i.e. non-$functionand non-$accumulatoroperators) is faster than$wherebecause it does not execute JavaScript and should be preferred if possible. -
However, if you must create custom expressions,
$functionis preferred over$where.
Unsupported Array and String Functions
MongoDB 6.0 upgrades the internal JavaScript engine used for server-side JavaScript, $accumulator, $function, and $where expressions 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 the 6.0 compatibility notes.
Examples
Example 1: Usage Example
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:
-
isFoundwhose value is determined by the custom$functionexpression that checks whether the MD5 hash of the name is equal to a specified hash. -
messagewhose value is determined by the custom$functionexpression that format a string message using a template.
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 ${name}. Your total score is ${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." }Example 2: Alternative to $where
Note
Aggregation Alternatives Preferred over $where
The $expr operator allows the use of aggregation expressions within the query language. And, starting in MongoDB 4.4, the $function and $accumulator allows users to define custom aggregation expressions in JavaScript if the provided pipeline operators cannot fulfill your application's needs.
Given the available aggregation operators:
-
The use of
$exprwith aggregation operators that do not use JavaScript (i.e. non-$functionand non-$accumulatoroperators) is faster than$wherebecause it does not execute JavaScript and should be preferred if possible. -
However, if you must create custom expressions,
$functionis preferred over$where.
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" } } } )