Definition
$functionDefines 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 |
|---|---|---|
String or Code | The function definition. You can specify the function definition as either BSON type Code or String. See also lang.
or
| |
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 | |
String | The language used in the body. You must specify |
Considerations
Schema Validation Restriction
You cannot use $function as part of a schema
validation query predicate.
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.In earlier versions, MongoDB does not allow JavaScript execution on
mongosinstances.
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.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.
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.
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." }
Tip
Starting in MongoDB 8.3, you can use $hexHash as a native aggregation alternative to hex_md5. $hexHash does not require server-side JavaScript and supports the SHA-256 and XXH64 algorithms in addition to MD5. Note that $hexHash returns an uppercase hexadecimal string, while hex_md5 returns lowercase. MD5 is a legacy algorithm and is disabled in FIPS mode.
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 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.
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" } } } )