我需要对需要在数组中旋转某些值的文档执行更新操作。 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);
}""", id, new_val)
我的分析结果非常不同:
> db.system.profile.find({op: "command"}, {"millis": 1})
{ "millis" : 13 }
{ "millis" : 14 }
{ "millis" : 14 }
...
从mongo shell和pymongo中运行相同的eval()
命令会导致服务器从pymongo运行相同的命令需要多花14ms才能有根本的不同吗?
答案 0 :(得分:1)
您看到的差异的一个可能原因(但不一定是 原因)是mongo
shell和mongod
服务器use Google's v8 Javascript engine默认情况下(虽然它可以配置为使用Spidermonkey作为替代)来解释您提供的命令。
Google的v8会看到Javascript代码中的热点,很可能是经常使用的JIT代码。
另一方面,vanilla PyMongo是written in pure Python,这意味着它将永远被解释,这是一个相当大的开销。
如果您还没有这样做,一种可能性是使用PyMongo extension written in C而不是默认值,或者如果应用程序的其余部分兼容,则使用Python的PyPy JIT解释器。
如果您使用从Debian派生的任何发行版(如Ubuntu),包python-pymongo-ext将为您提供C版PyMongo的预编译版本。