我有大量文档,我想提取一些统计数据。它需要每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并且在远程执行的mongo shell中执行超过1分钟,则需要3-4秒。
如何使这个服务器端javascript成为真正的服务器端执行?
更新
总结答案中提到的选项:
使用system.js
集合+ db.eval
:我不能使用它,因为eval
已被弃用,但eval
也需要在主服务器上运行,而且我有在辅助设备上运行它。
使用system.js
集合+ loadServerScripts
:它在mongo shell计算机中执行javascript代码,这是&#34;客户端&#34;。
cron job:我需要在特定节点上运行它,并且由于master可能会更改为另一个节点,我最终可以针对主节点运行它,我应该避免。但是,我不允许这样做,其中一个要求是在远程shell上运行它。 (有几个像这样的dbs需要这种统计数据,并且更容易只在一个地方使用它)。
答案 0 :(得分:1)
您可以将js代码存储为一种存储过程。
As per this article您可以将js存储为系统调用:
db.system.js.save({_id: "sum", value: function (x, y) { return x + y; }});
然后称之为:
db.eval("return sum(2, 3);");
当eval被折旧时 - 没有时间设置它将被禁用see here
db.loadServerScripts();
sum(3,2)
额外文档here
eval
的其他解决方案是让cron job
调用本地服务器上的javascript文件