Docs 菜单
Docs 主页
/
MongoDB Manual
/ / /

$function(聚合)

在此页面上

  • 定义
  • 语法
  • Considerations
  • 示例
$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, ...) { ... }

or

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

阵列

传递给函数的参数。如果函数不带参数,则可以指定一个空数组 [ ]

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

字符串

函数体中使用的语言。您必须指定 lang: "js"

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

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

如果您不使用 $function(或 $accumulator$wheremapReduce),请禁用服务器端脚本:

另请参阅 ➤使用安全配置选项运行 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表达式确定,该表达式检查名称的 MD 5哈希是否等于指定哈希。

  • 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