sorting documents by keys and directions
2 files changed, 77 insertions(+), 4 deletions(-)

M nosqlite.py
M tests.py
M nosqlite.py +13 -4
@@ 7,6 7,7 @@ import warnings
 from copy import deepcopy
 from functools import partial
 from itertools import starmap
+from operator import itemgetter
 
 try:
     from itertools import ifilter as filter, imap as map

          
@@ 14,6 15,9 @@ except ImportError:  # pragma: no cover 
     pass
 
 
+ASCENDING = False
+DESCENDING = True
+
 class MalformedQueryException(Exception):
     pass
 

          
@@ 217,7 221,7 @@ class Collection(object):
         document['_id'] = id
         return document
 
-    def find(self, query=None, skip=None, limit=None, hint=None):
+    def find(self, query=None, skip=None, limit=None, hint=None, sort=None):
         """
         Returns a list of documents in this collection that match a given query
         """

          
@@ 255,10 259,15 @@ class Collection(object):
                 results.append(match)
 
             # Just return if we already reached the limit
-            if limit and len(results) == limit:
-                return results
+            if limit and len(results) == limit and sort is None:
+                break
+        if sort:  # sort={key1:direction1, key2:direction2, ...}
+            sort_keys = list(sort.keys())
+            sort_keys.reverse()  # sort from right to left
+            for key in sort_keys:
+                results = sorted(results, key=itemgetter(key), reverse=sort[key])
 
-        return results
+        return results[:limit] if isinstance(limit, int) else results
 
     def _apply_query(self, query, document):
         """

          
M tests.py +64 -0
@@ 345,6 345,70 @@ class TestCollection(object):
                "WHERE type='table' and name like '{name}{{%}}'") 
         assert self.collection.db.execute(cmd.format(name=self.collection.name)).fetchone() is None
 
+    def test_find_with_sort(self):
+        self.collection.create()
+        self.collection.save({'a':1, 'b':'c'})
+        self.collection.save({'a':1, 'b':'a'})
+        self.collection.save({'a':5, 'b':'x'})
+        self.collection.save({'a':3, 'b':'x'})
+        self.collection.save({'a':4, 'b':'z'})
+        assert [
+            {'a':1, 'b':'c', '_id':1},
+            {'a':1, 'b':'a', '_id':2},
+            {'a':5, 'b':'x', '_id':3},
+            {'a':3, 'b':'x', '_id':4},
+            {'a':4, 'b':'z', '_id':5},
+        ] == self.collection.find()
+        assert [
+            {'a':1, 'b':'c', '_id':1},
+            {'a':1, 'b':'a', '_id':2},
+            {'a':3, 'b':'x', '_id':4},
+            {'a':4, 'b':'z', '_id':5},
+            {'a':5, 'b':'x', '_id':3},
+        ] == self.collection.find(sort={'a':nosqlite.ASCENDING})
+        assert [
+            {'a':1, 'b':'a', '_id':2},
+            {'a':1, 'b':'c', '_id':1},
+            {'a':5, 'b':'x', '_id':3},
+            {'a':3, 'b':'x', '_id':4},
+            {'a':4, 'b':'z', '_id':5},
+        ] == self.collection.find(sort={'b':nosqlite.ASCENDING})
+        assert [
+            {'a':5, 'b':'x', '_id':3},
+            {'a':4, 'b':'z', '_id':5},
+            {'a':3, 'b':'x', '_id':4},
+            {'a':1, 'b':'c', '_id':1},
+            {'a':1, 'b':'a', '_id':2},
+        ] == self.collection.find(sort={'a':nosqlite.DESCENDING})
+        assert [
+            {'a':4, 'b':'z', '_id':5},
+            {'a':5, 'b':'x', '_id':3},
+            {'a':3, 'b':'x', '_id':4},
+            {'a':1, 'b':'c', '_id':1},
+            {'a':1, 'b':'a', '_id':2},
+        ] == self.collection.find(sort={'b':nosqlite.DESCENDING})
+        assert [
+            {'a':1, 'b':'a', '_id':2},
+            {'a':1, 'b':'c', '_id':1},
+            {'a':3, 'b':'x', '_id':4},
+            {'a':4, 'b':'z', '_id':5},
+            {'a':5, 'b':'x', '_id':3},
+        ] == self.collection.find(sort={'a':nosqlite.ASCENDING, 'b':nosqlite.ASCENDING})
+        assert [
+            {'a':5, 'b':'x', '_id':3},
+            {'a':4, 'b':'z', '_id':5},
+            {'a':3, 'b':'x', '_id':4},
+            {'a':1, 'b':'a', '_id':2},
+            {'a':1, 'b':'c', '_id':1},
+        ] == self.collection.find(sort={'a':nosqlite.DESCENDING, 'b':nosqlite.ASCENDING})
+        assert [
+            {'a':5, 'b':'x', '_id':3},
+            {'a':4, 'b':'z', '_id':5},
+            {'a':3, 'b':'x', '_id':4},
+            {'a':1, 'b':'c', '_id':1},
+            {'a':1, 'b':'a', '_id':2},
+        ] == self.collection.find(sort={'a':nosqlite.DESCENDING, 'b':nosqlite.DESCENDING})
+
     @mark.parametrize('strdoc,doc', [
         ('{"foo": "bar"}', {'_id': 1, 'foo': 'bar'}),
         (u'{"foo": "☃"}', {'_id': 1, 'foo': u'☃'}),