文档菜单
文档首页
/
MongoDB 手册
/ / /

$function(聚合函数)

本页内容

  • 定义
  • 语法
  • 注意事项
  • 示例
$function

重要

服务器端JavaScript已弃用

从MongoDB 8.0开始,服务器端JavaScript函数($accumulator, $function$where)已弃用。运行这些函数时,MongoDB会记录警告。

使用JavaScript定义自定义聚合函数或表达式。

您可以使用$function运算符来定义自定义函数,以实现MongoDB查询语言不支持的行为。另请参阅$accumulator

重要

在聚合表达式中执行JavaScript可能会降低性能。只有当提供的$function运算符无法满足应用程序需求时,才使用它。

操作符 $function 的语法如下

{
$function: {
body: <code>,
args: <array expression>,
lang: "js"
}
}
字段
类型
描述
字符串或代码

函数定义。您可以指定函数定义,可以是 BSON 类型的 Code 或 String。另请参阅 lang.

function(arg1, arg2, ...) { ... }

"function(arg1, arg2, ...) { ... }"

数组

传递给函数 body 的参数。如果 body 函数不接受参数,您可以指定一个空数组 [ ]

数组元素可以是任何 BSON 类型,包括 Code。请参阅 示例 2:$where 的替代方案。

字符串

用于 body 的语言。您必须指定 lang: "js"

您不能将 $function 用作模式验证查询谓词的一部分。

要使用 $function,您必须启用服务器端脚本(默认设置)。

如果您不使用 $function(或 $accumulator$where,或 mapReduce),则禁用服务器端脚本

另请参阅 ➤ 使用安全配置选项运行 MongoDB。

查询运算符 $where 也可以用于指定 JavaScript 表达式。然而

  • 操作符 $expr 允许在查询语言中使用 聚合表达式

  • 操作符 $function$accumulator 允许用户在提供的管道操作符无法满足应用程序需求时,在 JavaScript 中定义自定义的聚合表达式。

给定可用的聚合操作符

  • 使用 $expr 与不使用 JavaScript(即非 $function 和非 $accumulator 操作符)的聚合操作符,比使用 $where 更快,因为它不执行 JavaScript,如果可能的话,应优先选择。

  • 然而,如果您必须创建自定义表达式,则 $function 比使用 $where 更受青睐。

MongoDB 6.0 升级了用于 服务器端 JavaScript$accumulator$function$where 表达式的内部 JavaScript 引擎,从 MozJS-60 升级到 MozJS-91。MozJS-91 中移除了 MozJS-60 中存在的一些已弃用、非标准数组字符串函数。

有关移除的数组字符串函数的完整列表,请参阅 6.0 兼容性说明

使用以下文档创建一个名为 players 的示例集合

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 ] }
])

以下聚合操作使用 $addFields 在每个文档中添加新字段

  • isFound 的值由自定义的 $function 表达式确定,该表达式检查名称的 MD5 哈希是否等于指定的哈希。

  • message 的值由自定义的 $function 表达式确定,该表达式使用模板格式化字符串消息。

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"
}
}
}
}
] )

操作返回以下文档

{ "_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." }

注意

优先使用聚合替代方案而非 $where

$expr 运算符允许在查询语言中使用聚合表达式。而$function$accumulator 允许用户在提供的管道运算符无法满足应用程序需求时,在 JavaScript 中定义自定义的聚合表达式。

给定可用的聚合操作符

  • 使用 $expr 与不使用 JavaScript(即非 $function 和非 $accumulator 操作符)的聚合操作符,比使用 $where 更快,因为它不执行 JavaScript,如果可能的话,应优先选择。

  • 然而,如果您必须创建自定义表达式,则 $function 比使用 $where 更受青睐。

作为使用 $where 运算符的查询的替代方案,您可以使用 $expr$function。例如,考虑以下 $where 示例。

db.players.find( { $where: function() {
return (hex_md5(this.name) == "15b0a220baa16331e8d80e15367677ad")
} } );

db.collection.find() 操作返回以下文档

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

该示例可以使用 $expr$function 表达:

db.players.find( {$expr: { $function: {
body: function(name) { return hex_md5(name) == "15b0a220baa16331e8d80e15367677ad"; },
args: [ "$name" ],
lang: "js"
} } } )

返回上一页

$floor