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

本文涉及的产品
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
简介: 虽然官方不推荐使用将业务逻辑存储在数据库中,并且提示在 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

相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。   相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
目录
相关文章
|
8天前
|
存储 数据挖掘 数据库
服务器数据恢复—EMC UNITY 400存储卷被误删除的数据恢复案例
EMC Unity 400存储连接了2台硬盘柜。2台硬盘柜上一共有21块硬盘(520字节)。21块盘组建了2组RAID6:一组有11块硬盘,一组有10块硬盘。 在存储运行过程中,管理员误操作删除了 2组POOL上的部分数据卷。
|
19天前
|
存储 NoSQL JavaScript
Node.js导入MongoDB具体操作指南
通过本文,您已经学会了如何在Node.js中导入MongoDB并执行基本的CRUD操作。Node.js与MongoDB的结合使得构建高效、可扩展的后端服务变得更加容易。通过遵循本文的步骤,您可以快速设置并运行一个强大的数据存储和处理系统。希望这篇指南能为您的开发工作提供实用的帮助。
48 13
|
16天前
|
存储 算法 数据挖掘
服务器数据恢复—nas中raid6阵列失效,存储无法访问的数据恢复案例
一台nas上共有14块硬盘组建了一组raid6磁盘阵列。 该nas在工作过程中,raid6阵列中硬盘出现故障离线,导致raid6阵列失效,nas无法正常访问。
|
23天前
|
存储 数据挖掘 数据库
服务器数据恢复—OceanStor存储数据恢复案例
华为OceanStor T系列某型号存储中有一组由24块机械硬盘组建的一组RAID5阵列。 运行过程中该存储设备RAID5阵列上多块硬盘出现故障离线,阵列失效,存储中数据无法访问。
|
29天前
|
存储 NoSQL MongoDB
【赵渝强老师】MongoDB逻辑存储结构
MongoDB的逻辑存储结构由数据库(Database)、集合(Collection)和文档(Document)组成,形成层次化数据模型。用户通过mongoshell或应用程序操作这些结构。视频讲解及结构图详见下文。
|
1月前
|
存储 数据挖掘
服务器数据恢复—V7000存储上多块Mdisk成员盘出现故障的数据恢复案例
服务器存储数据恢复环境: 一台V7000存储上共12块SAS机械硬盘(其中1块是热备盘),组建了2组Mdisk,创建了一个pool。挂载在小型机上作为逻辑盘使用,小型机上安装的AIX+Sybase。 服务器存储故障: V7000存储中磁盘出现故障,管理员发现问题后立即更换磁盘。新更换的硬盘在上线同步数据的时候,存储上另一块磁盘也出现问题,导致逻辑盘无法挂接在小型机上,业务暂时中断。V7000存储的管理界面上显示两块硬盘故障脱机。 pool无法加载,其中三个通用卷均无法挂载。
|
1月前
|
存储 JavaScript 前端开发
JavaScript中的数据类型以及存储上的差别
通过本文的介绍,希望您能够深入理解JavaScript中的数据类型及其存储差别,并在实际编程中灵活运用这些知识,以提高代码的性能和稳定性。
55 3
|
1月前
|
机器学习/深度学习 JavaScript Cloud Native
Node.js作为一种快速、可扩展的服务器端运行时环境
Node.js作为一种快速、可扩展的服务器端运行时环境
56 8
|
1月前
|
存储 运维 数据挖掘
服务器数据恢复—EVA存储中多块硬盘离线导致存储崩溃的数据恢复案例
一台HP EVA存储中有23块硬盘,挂接到一台windows server操作系统的服务器。 EVA存储上有三个硬盘指示灯亮黄灯,此刻存储还能正常使用。管理员在更换硬盘的过程中,又出现一块硬盘对应的指示灯亮黄灯,存储崩溃,无法使用了。
|
2月前
|
JavaScript
使用Node.js创建一个简单的Web服务器
使用Node.js创建一个简单的Web服务器

热门文章

最新文章