MongoDB服务器端的JavaScript实际上是客户端的吗?

3
我有一大批文档,想要从中提取一些统计数据。需要每15分钟定期执行。
大多数统计数据都基于文档大小,因此需要获取文档并计算其大小。
我的统计输出只是一行带有一些关于文档大小的统计数据。(我并不获取整个集合,而只是其中的一个子集,因此无法使用mongodb提供的集合统计信息)
我想在服务器端执行此操作,并避免将所有文档传输到客户端(仅因为我需要计算大小)。
我使用mongo shell执行它,确保连接到辅助节点,而且这个mongo shell始终在远程机器上运行,所以这是避免通过网络传输所有文档的主要原因。
阅读了mongo shell文档后,我期望它能够像它所述的那样在“服务器端”执行,但实际上它并没有这样工作,而是在与mongo shell相同的机器上执行(在我看来,这比客户端更加客户端化)。
为了帮助您更好地理解,我在此贴出了代码片段:
db.cache.find(query).forEach(function(obj) {

        var curr = Object.bsonsize(obj); 

        if(stats.max < curr) {
            stats.max = curr;
            stats.maxid = obj._id;
        } 
        if(stats.min > curr) {
            stats.min = curr;
        } 
        stats.count++;
        stats.total += curr;

        stats.avg = stats.total/stats.count;
    })

如果我在本地执行mongo shell,大约需要3-4秒,而在远程执行mongo shell,则需要超过1分钟。
有什么想法可以使这个服务器端JavaScript成为真正的服务器端执行?
更新: 总结答案中提到的选择: - 使用system.js集合+db.eval:由于eval已被弃用,因此无法使用它,但还需要在主节点上运行它,并且我必须在次要节点上运行它。 - 使用system.js集合+loadServerScripts:它在mongo shell机器上执行javascript代码,即“客户端”。 - 定时作业:我需要在特定节点上运行它,因为主节点可能更改为另一个节点,所以我可能会对主节点进行操作,这是我应该避免的。但是,我也不允许这样做,其中一个要求是在远程shell上运行它。(有几个类似于这些的数据库将需要这种统计信息,并且将它们放在一个地方更容易维护)。

ssh 到 MongoDB 服务器,打开 Mongo shell 并在其中执行代码。 - sapy
在 REPL 中运行的 js 显然在运行 REPL 进程的同一台机器上执行。直接在 mongodb 服务器上运行 REPL 即可。 - vp_arth
无法通过ssh连接到Mongo服务器。这是一个生产环境,我永远也没有权限这么做 :( - richardtz
我该如何直接在MongoDB服务器上运行REPL? - richardtz
1个回答

2
你可以将js代码存储为一种“存储过程”。
根据这篇文章,你可以将js代码存储为系统调用。
 db.system.js.save({_id: "sum", value: function (x, y) { return x + y; }});

然后像这样调用:

db.eval("return sum(2, 3);");

由于eval已经被弃用,目前没有确定停用的时间点。详情请参见此处
db.loadServerScripts();
sum(3,2) 

更多的文档在此

eval的另一种解决方案是定时调用在服务器上本地启动的javascript文件的cron job


@richardtz,既然您可以访问Mongo控制台,那么您可以执行:db.loadServerScripts(); - 我是对的吗?或者您会有一个将通过cron调用的脚本吗? - profesor79
我不确定您所说的“mongo console”的含义。我正在使用mongo shell来执行我的脚本。这个mongo shell是在远程机器上运行的。如果我使用eval,那么我的代码将在服务器上执行->可以但已经过时。如果我使用loadServerScripts,则我的代码将在远程机器而不是服务器上执行。 - richardtz
@richardtz - eval 的另一种解决方案是使用 cron job 调用在服务器上本地启动的 JavaScript 文件。 - profesor79
我也遇到了cron方法的问题,因为我不知道哪个实例将是主要的,而我需要在次要实例上执行它。 - richardtz
让我们在聊天中继续这个讨论 - richardtz
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接