我需要对需要在数组中旋转某些值的文档执行更新操作. MongoDB更新查询当前不允许您弹出$pop,然后$push更新中的同一字段.在网上搜索建议之后,我决定db.eval()最适合我的使用,因为它确保原子性,并且我执行的操作非常短,所以它不会锁定数据库太久.
以下是我想要做的一个例子:
db.eval(function (id,newVal) { doc = db.collection.findOne({_id: id}); doc.values.shift(); doc.values.push(newVal); db.collection.save(doc); },id,newVal);
这样做完美!然后,我启用了mongoDB分析,以查看eval()命令所用的毫秒数,我总是得到的结果少于1毫秒:
> db.system.profile.find({op: "command"},{"millis": 1}) { "millis" : 0 } { "millis" : 0 } ...
对我来说这是个好消息,除了我的应用程序在Python中,所以我使用pymongo客户端来执行eval()命令. (上面的数据来自mongo shell)但是现在,当我使用pymongo运行相同的eval()命令时:
conn = pymongo.Connection(mongo_server_hostname) db = conn.my_db db.eval("""function (id,newVal) { doc = db.collection.findOne({_id: id}); doc.values.shift(); doc.values.push(newVal); db.collection.save(doc); }""",new_val)
我得到非常不同的分析结果:
> db.system.profile.find({op: "command"},{"millis": 1}) { "millis" : 13 } { "millis" : 14 } { "millis" : 14 } ...
在mongo shell和pymongo中运行相同的eval()命令有什么根本不同的结果,导致服务器从pymongo运行相同的命令需要14ms?
您所看到的一个可能的原因(但不一定是原因),默认情况下是mongo shell和mongod server
use Google’s v8 Javascript engine(尽管可以配置为使用Spidermonkey作为替代),以解释您给出的命令.
原文链接:https://www.f2er.com/bash/386650.htmlGoogle的v8会在Javascript代码中看到热点,并且可能会经常使用JIT代码.
另一方面,香草PyMongo是written in pure Python,这意味着它将永远被解释,这是一个相当大的开销.
如果您还没有这样做,一个可能的办法是使用PyMongo extension written in C而不是默认的,或者如果您的其他应用程序兼容,则使用Python的PyPy JIT解释器.
如果您使用从Debian(如Ubuntu)派生的任何发行版,则python-pymongo-ext软件包可为您提供PyMongo的C版本的预编译版本.