This commit is contained in:
Mike Dirolf 2009-01-30 12:22:13 -05:00
parent f5fbb8cb68
commit 2a4fba7aa4
2 changed files with 41 additions and 0 deletions

View File

@ -22,6 +22,7 @@ from dbref import DBRef
from son_manipulator import ObjectIdInjector, ObjectIdShuffler
from collection import Collection
from errors import InvalidName, CollectionInvalid, OperationFailure
from code import Code
# sort directions
ASCENDING = 1
@ -345,3 +346,23 @@ class Database(object):
if not isinstance(dbref, DBRef):
raise TypeError("cannot dereference a %s" % type(dbref))
return self[dbref.collection()].find_one(dbref.id())
def eval(self, code, *args):
"""Evaluate a JavaScript expression on the Mongo server.
Useful if you need to touch a lot of data lightly; in such a scenario
the network transfer of the data could be a bottleneck. The `code`
argument must be a JavaScript function. Additional positional
arguments will be passed to that function when it is run on the
server.
Raises TypeError if `code` is not an instance of (str, unicode). Raises
OperationFailure if the eval fails. Returns the result of the
evaluation.
"""
if not isinstance(code, types.StringTypes):
raise TypeError("code must be an instance of (str, unicode)")
command = SON([("$eval", Code(code)), ("args", args)])
result = self._command(command)
return result.get("retval", None)

View File

@ -247,6 +247,26 @@ class TestDatabase(unittest.TestCase):
key = db.test.save(obj)
self.assertEqual(obj, db.dereference(DBRef("test", key)))
def test_eval(self):
db = self.connection.pymongo_test
db.test.remove({})
self.assertRaises(TypeError, db.eval, None)
self.assertRaises(TypeError, db.eval, 5)
self.assertRaises(TypeError, db.eval, [])
self.assertEqual(3, db.eval("function (x) {return x;}", 3))
self.assertEqual(3, db.eval(u"function (x) {return x;}", 3))
self.assertEqual(None, db.eval("function (x) {db.test.save({y:x});}", 5))
self.assertEqual(db.test.find_one()["y"], 5)
self.assertEqual(5, db.eval("function (x, y) {return x + y;}", 2, 3))
self.assertEqual(5, db.eval("function () {return 5;}"))
self.assertEqual(5, db.eval("2 + 3;"))
self.assertRaises(OperationFailure, db.eval, "5 ++ 5;")
# TODO some of these tests belong in the collection level testing.
def test_save_find_one(self):
db = Database(self.connection, "pymongo_test")