在mongodb服务器上存储和执行 js 函数 - 存储过程

简介: 虽然官方不推荐使用将业务逻辑存储在数据库中,并且提示在 mongodb 中执行 javascript 存在性能限制。但实际上,将 javascript 函数存储在 mongodb 中执行,还是非常有必要的,更方便,许多场景下性能会更好(在执行大量查询处理时不需要将数据传回客户端引擎)。在目前的版本中,我们任然可以将 javascript 函数存储在 mongodb 内置的一个特殊集合 db.system.js 中,然后这些变量就可以在任何 mongodb 的 javascript 上下文中调用,包括:db.eval()、$where子句、mapReduce。自从 mongodb 3

虽然官方不推荐使用将业务逻辑存储在数据库中,并且提示在 mongodb 中执行 javascript 存在性能限制。

但实际上,将 javascript 函数存储在 mongodb 中执行,还是非常有必要的,更方便,许多场景下性能会更好(在执行大量查询处理时不需要将数据传回客户端引擎)。

在目前的版本中,我们任然可以将 javascript 函数存储在 mongodb 内置的一个特殊集合 db.system.js 中,然后这些变量就可以在任何 mongodb 的 javascript 上下文中调用,包括:db.eval()、$where子句、mapReduce。

自从 mongodb 3.0 版本及之后,执行 db.eval() 会得到一个 Warning: db.eval is deprecated,意味着该 api 在未来即将被删除。但目前社区还没有提供类似的替代方案,并且该 api 在最新的 mongodb 4.0 版本中任然可以正常使用。

相关讨论可以参考: SERVER-17453 warn that db.eval() / eval command is deprecated - MongoDB

如何使用
首先登陆 mongo shell

$ mongo

use testdb
新增一个函数
db.system.js.save({
_id: 'doSomeThing', // 存储过程名称
value(args) { // 过程体
return db.courses.count();

},
description: 'just a test.', // 描述,非必须
});
或者

db.system.js.insert({
_id: 'doSomeThing', // 存储过程名称
value(args) { // 过程体

return db.courses.count();

},
description: 'just a test.', // 描述,非必须
});
修改已经存在的函数
db.system.js.update(
{

_id: 'doSomeThing', // 存储过程名称

},
{

value() { // 过程体
  return db.courses.count();
},

}
);
注意,新增时的参数是一个 object,而修改(update)时的参数类似 db.collect.update(, ),两个参数均为 object。
执行
// 使用 eval 命令
db.runCommand({

eval:"doSomeThing(args)",
args: null,
nolock: true

});

// 或者使用 helper 方法 db.eval
db.eval("doSomeThing(args)");
// 也可以立即执行一个函数
db.eval(function(arg1,arg2){}, arg1, arg2);
查看已经存储的 javascript 函数
db.system.js.find();
注意事项
写锁定
需要注意的是,执行 db.eval() 时,mongodb 采用了全局写锁定,因此,执行 db.eval() 时将阻止对数据库的所有其他读写操作,意味着将阻塞其他任务,直到 db.eval() 执行结束,这在执行长时间任务时有些麻烦。

使用 eval 命令也同样存在全局写锁定,但可以设置 nolock 选项避免。db.eval() 和 eval 命令的不同之处只是不支持 nolock 选项。

javascript 解释器
一般来说,我们使用 mongo 命令登陆 shell,此时使用的是 mongoshell 的 javascript 解释器,不同版本的 shell 所支持的语法并不同。 而论坛使用 eval 命令或者 db.eval() 时,所使用的 javascript 解释器为服务器的解释器,这和 mongoshell 有所区别。

此外,在 mongodb 3.2 中,mongoshell 和服务器端的 javascript 引擎由 V8 更改为 SpiderMonkey 。你可以在 shell 中执行 db.serverBuildInfo() ,查看结果中的 javascriptEngine 字段确认当前使用的 javascript 引擎。

SpiderMonkey 增加了对 ES6 的支持,包括箭头函数、解构等。但仅此而已,实测 mongodb 4.0 版本中仍然不支持这样的语法: const obj={...obj1}; 。

所以,在编写 javascript 函数时,需要注意 mongodb 的版本差异和内置的 javascript 引擎类型,避免语法错误。

访问限制
自 mongodb 2.6 版本之后,如果启用了密码登陆,则必须有权访问所有资源上的所有操作才能运行 eval。

注:这样会导致安全风险。
如果你确定要这么做,可以创建一个拥有 anyAction 和 anyResource 的角色,并添加一个对应的用户。

use admin
db.createRole({
role: 'sysadmin',
roles: [],
privileges: [

{
  resource: { anyResource: true },
  actions: [ 'anyAction' ],
},

],
});

use dbtest
db.createUser({
user: 'root',
pwd: 'root',
roles: [

{ role: 'sysadmin', db: 'admin' },

],
});
最后
除了以上介绍的方法以外,mongodb 还支持其他直接执行 javascript 的方案,例如 mongoshell 中所支持的 load() 方法可以直接加载一个 js 文件并执行。

鉴于篇幅所限,更多介绍可以参考官方文档:Server-side JavaScript — MongoDB Manual

目录
相关文章
|
2月前
|
存储 运维 数据挖掘
服务器数据恢复—EqualLogic存储硬盘出现坏道的数据恢复案例
某品牌EqualLogic PS6100存储阵列上有一组由16块硬盘组建的raid5磁盘阵列。磁盘阵列上层划分多个大小不同的卷,存放虚拟机文件。 硬盘出现故障导致存储阵列不可用,需要恢复存储阵列中的数据。
|
2月前
|
存储 运维 Oracle
服务器数据恢复—存储硬盘指示灯亮黄灯,RAID5阵列崩溃的数据恢复案例
服务器存储数据恢复环境: 某单位一台某品牌DS5300存储,1个机头+4个扩展柜,50块的硬盘组建了两组RAID5阵列。一组raid5阵列有27块硬盘,存放Oracle数据库文件。存储系统上层一共划分了11个卷。 服务器存储故障: 存储设备上两个硬盘指示灯亮黄色。其中一组RAID5阵列崩溃,存储不可用,设备已经过保。
|
5月前
|
存储 Oracle 关系型数据库
服务器数据恢复—光纤存储上oracle数据库数据恢复案例
一台光纤服务器存储上有16块FC硬盘,上层部署了Oracle数据库。服务器存储前面板2个硬盘指示灯显示异常,存储映射到linux操作系统上的卷挂载不上,业务中断。 通过storage manager查看存储状态,发现逻辑卷状态失败。再查看物理磁盘状态,发现其中一块盘报告“警告”,硬盘指示灯显示异常的2块盘报告“失败”。 将当前存储的完整日志状态备份下来,解析备份出来的存储日志并获得了关于逻辑卷结构的部分信息。
|
5月前
|
存储
阿里云轻量应用服务器收费标准价格表:200Mbps带宽、CPU内存及存储配置详解
阿里云香港轻量应用服务器,200Mbps带宽,免备案,支持多IP及国际线路,月租25元起,年付享8.5折优惠,适用于网站、应用等多种场景。
1876 0
|
6月前
|
存储 运维 API
HPE OneView 10.0 - HPE 服务器、存储和网络设备集中管理软件
HPE OneView 10.0 - HPE 服务器、存储和网络设备集中管理软件
136 1
|
7月前
|
存储 数据挖掘
服务器数据恢复—EMC存储raid5阵列数据恢复案例
服务器存储数据恢复环境: EMC某型号存储中有一组由8块硬盘组建的raid5磁盘阵列。 服务器存储故障: raid5阵列中有2块硬盘离线,存储不可用,上层应用崩了。
|
7月前
|
存储 运维 数据挖掘
服务器数据恢复—EqualLogic存储硬盘出现坏道的数据恢复案例
一台EqualLogic某型号存储中有一组由16块SAS硬盘组建的RAID5阵列。上层采用VMFS文件系统,存放虚拟机文件,上层一共分了4个卷。 磁盘故障导致存储不可用,且设备已经过保。
|
3月前
|
存储 数据挖掘 Linux
服务器数据恢复—重装系统导致OceanStor存储上的分区无法访问的数据恢复案例
服务器存储数据恢复环境: 华为OceanStor某型号存储+扩展盘柜,存储中的硬盘组建了raid5磁盘阵列,上层分配了1个lun。 linux操作系统,划分了两个分区,分区一通过lvm扩容,分区二为xfs文件系统。 服务器存储故障: 工作人员重装系统操作失误导致磁盘分区变化,分区二无法访问,数据丢失。
|
4月前
|
存储 算法 数据挖掘
服务器数据恢复—昆腾存储StorNext文件系统数据恢复案例
一台昆腾存储设备中有一组raid5磁盘阵列。阵列上有两块硬盘先后离线,raid5磁盘阵列不可用。
|
4月前
|
存储 监控 Linux
Dell OpenManage Enterprise 4.5 - Dell 服务器、存储和网络设备集中管理软件
Dell OpenManage Enterprise 4.5 - Dell 服务器、存储和网络设备集中管理软件
123 0

推荐镜像

更多