#47
authoradam <adamansky@gmail.com>
Thu, 14 Feb 2013 17:59:38 +0000 (00:59 +0700)
committeradam <adamansky@gmail.com>
Thu, 14 Feb 2013 17:59:38 +0000 (00:59 +0700)
pyejdb/pyejdb/__init__.py
pyejdb/test/test_one.py

index a3e60b6..fcded16 100644 (file)
@@ -20,8 +20,9 @@ import _pyejdb
 from functools import lru_cache
 from pyejdb import bson
 from pyejdb.typecheck import *
-import re
-import numbers
+from collections import OrderedDict as odict
+import re, numbers
+
 
 __all__ = [
 
@@ -192,9 +193,10 @@ class EJDB(object):
                otherwise updated documents will be fully replaced by new instances.
         """
         for doc in jsarr:
-            _oid = self.__ejdb.save(cname, bson.serialize_to_bytes(doc), **kwargs)
-            if "_id" not in doc:
-                doc["_id"] = _oid
+            if doc is not None:
+                _oid = self.__ejdb.save(cname, bson.serialize_to_bytes(doc), **kwargs)
+                if "_id" not in doc:
+                    doc["_id"] = _oid
 
     @typecheck
     def load(self, cname : str, oid : str):
@@ -221,13 +223,14 @@ class EJDB(object):
         return self.__ejdb.remove(cname, oid)
 
     @typecheck
-    def find(self, cname : str, qobj : optional(dict)=None, *args, **kwargs):
+    def find(self, cname : str, qobj : optional(dict)=None,
+             *args, **kwargs):
         """ Execute query on collection.
 
         Sample:
         >>> # Fetch all elements from collection
         >>> ejdb.find("mycoll")
-        >>> # Query document with 'foo==bar' condition, include in result doc only 'foo' and '_id' field
+        >>> # Query document with 'foo==bar' condition, include in resulting doc 'foo' and '_id' fields only
         >>> ejdb.find("mycoll", {'foo' : 'bar'}, hints={$fields : {'foo' : 1, '_id' : 1}});
 
         General format:
@@ -310,26 +313,22 @@ class EJDB(object):
                If field presented in $orderby clause it will be forced to include in resulting records.
                Example:
                hints:    {
-                   "$orderby" : { //ORDER BY field1 ASC, field2 DESC
-                       "field1" : 1,
-                       "field2" : -1
-                   },
+                   "$orderby" : [ //ORDER BY field1 ASC, field2 DESC
+                       ("field1", 1),
+                       ("field2", -1)
+                   ],
                    "$fields" : { //SELECT ONLY {_id, field1, field2}
                        "field1" : 1,
                        "field2" : 1
                    }
                }
 
-        .. NOTE:: In order to preserve ORDER BY fields sequence you have to use OrderedDict:
-                  >>> from collections import OrderedDict as odict
-                  >>> ejdb.find("mycoll", hints={ $orderby : odict([("field1", 1), ("field2", -1)]) })
-
         :Returns:
             Resultset cursor :class:`EJDBCursorWrapper`
         """
         if not qobj: qobj = {}
         qobj = bson.serialize_to_bytes(qobj)
-        hints = bson.serialize_to_bytes(kwargs.get("hints", {}))
+        hints = bson.serialize_to_bytes(self.__preprocessQHints(kwargs.get("hints", {})))
         orarr = [bson.serialize_to_bytes(x) for x in args]
         qflags = kwargs.get("qflags", 0)
         cursor = self.__ejdb.find(cname, qobj, orarr, hints, qflags)
@@ -338,7 +337,7 @@ class EJDB(object):
     def findOne(self, cname : str, qobj : optional(dict)=None, *args, **kwargs):
         """ Same as `#find()` but retrieves only one matching JSON object.
         """
-        hints = kwargs.get("hints", {})
+        hints = self.__preprocessQHints(kwargs.get("hints", {}))
         hints["$max"] = 1
         kwargs["hints"] = hints
         with self.find(cname, qobj, *args, **kwargs) as res:
@@ -393,7 +392,7 @@ class EJDB(object):
 
     @typecheck
     def ensureCollection(self, cname : str, **kwargs):
-        """ Automatically creates new collection if it does't exists.
+        """ Automatically creates new collection if it does not exists.
         Collection options `copts`
         are applied only for newly created collection.
         for existing collections `copts` takes no effect.
@@ -445,37 +444,60 @@ class EJDB(object):
 
     @typecheck
     def ensureIStringIndex(self, cname : str, path : str):
+        """ Ensure case insensitive String index for JSON field path.
+        """
         return self.__ejdb.setIndex(cname, path, _pyejdb.JBIDXISTR)
 
     @typecheck
     def rebuildIStringIndex(self, cname : str, path : str):
+        """Rebuild case insensitive String index for JSON field path.
+        """
         return self.__ejdb.setIndex(cname, path, _pyejdb.JBIDXISTR | _pyejdb.JBIDXREBLD)
 
     @typecheck
     def dropIStringIndex(self, cname : str, path : str):
+        """Drop case insensitive String index for JSON field path.
+        """
         return self.__ejdb.setIndex(cname, path, _pyejdb.JBIDXISTR | _pyejdb.JBIDXDROP)
 
     @typecheck
     def ensureNumberIndex(self, cname : str, path : str):
+        """Ensure index presence of Number type for JSON field path.
+        """
         return self.__ejdb.setIndex(cname, path, _pyejdb.JBIDXNUM)
 
     @typecheck
     def rebuildNumberIndex(self, cname : str, path : str):
+        """Rebuild index of Number type for JSON field path.
+        """
         return self.__ejdb.setIndex(cname, path, _pyejdb.JBIDXNUM | _pyejdb.JBIDXREBLD)
 
     @typecheck
     def dropNumberIndex(self, cname : str, path : str):
+        """Drop index of Number type for JSON field path.
+        """
         return self.__ejdb.setIndex(cname, path, _pyejdb.JBIDXNUM | _pyejdb.JBIDXDROP)
 
     @typecheck
     def ensureArrayIndex(self, cname : str, path : str):
+        """Ensure index presence of Array type for JSON field path.
+        """
         return self.__ejdb.setIndex(cname, path, _pyejdb.JBIDXARR)
 
     @typecheck
     def rebuildArrayIndex(self, cname : str, path : str):
+        """Rebuild index of Array type for JSON field path.
+        """
         return self.__ejdb.setIndex(cname, path, _pyejdb.JBIDXARR | _pyejdb.JBIDXREBLD)
 
     @typecheck
     def dropArrayIndex(self, cname : str, path : str):
+        """Drop index of Array type for JSON field path.
+        """
         return self.__ejdb.setIndex(cname, path, _pyejdb.JBIDXARR | _pyejdb.JBIDXDROP)
 
+    def __preprocessQHints(self, hints : dict):
+        val = hints.get("$orderby")
+        if isinstance(val, list):
+            hints["$orderby"] = odict(val)
+        return hints
index 52b429c..a8922b3 100644 (file)
 #  if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 #  Boston, MA 02111-1307 USA.
 # *************************************************************************************************
+from datetime import datetime
 
 import unittest
+from pyejdb import bson
 import pyejdb
+import re
+from collections import OrderedDict as odict
 
 class TestOne(unittest.TestCase):
     def __init__(self, *args, **kwargs):
@@ -76,7 +80,65 @@ class TestOne(unittest.TestCase):
 
 
     def test2(self):
-        pass
+        ejdb = TestOne._ejdb
+        self.assertEqual(ejdb.isopen, True)
+        parrot1 = {
+            "name": "Grenny",
+            "type": "African Grey",
+            "male": True,
+            "age": 1,
+            "birthdate": datetime.utcnow(),
+            "likes": ["green color", "night", "toys"],
+            "extra1": None
+        }
+
+        parrot2 = {
+            "name": "Bounty",
+            "type": "Cockatoo",
+            "male": False,
+            "age": 15,
+            "birthdate": datetime.utcnow(),
+            "likes": ["sugar cane"],
+            "extra1": None
+        }
+        ejdb.save("parrots", *[parrot1, None, parrot2])
+        self.assertIsInstance(parrot1["_id"], str)
+        self.assertIsInstance(parrot2["_id"], str)
+        p2 = ejdb.load("parrots", parrot2["_id"])
+        self.assertEqual(p2["_id"], parrot2["_id"])
+
+        cur = ejdb.find("parrots")
+        self.assertEqual(len(cur), 2)
+        self.assertEqual(len(cur[1:]), 1)
+        self.assertEqual(len(cur[2:]), 0)
+
+        cur = ejdb.find("parrots",
+                {"name": bson.BSON_Regex(("(grenny|bounty)", "i"))},
+                        hints={"$orderby": [("name", 1)]})
+        self.assertEqual(len(cur), 2)
+        self.assertEqual(cur[0]["name"], "Bounty")
+        self.assertEqual(cur[0]["age"], 15)
+
+        cur = ejdb.find("parrots", {}, {"name": "Grenny"}, {"name": "Bounty"},
+                        hints={"$orderby": [("name", 1)]})
+        self.assertEqual(len(cur), 2)
+
+        cur = ejdb.find("parrots", {}, {"name": "Grenny"},
+                        hints={"$orderby": [("name", 1)]})
+        self.assertEqual(len(cur), 1)
+
+        sally = {
+            "name": "Sally",
+            "mood": "Angry",
+        }
+        molly = {
+            "name": "Molly",
+            "mood": "Very angry",
+            "secret": None
+        }
+        ejdb.save("birds", *[sally, molly])
+        ejdb.ensureStringIndex("birds", "name")
+
 
     @classmethod
     def tearDownClass(cls):