@@ 7,7 7,6 @@ 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
@@ 221,6 220,11 @@ class Collection(object):
document['_id'] = id
return document
+ def __get_val(self, item, key):
+ for k in key.split('.'):
+ item = item.get(k)
+ return item
+
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
@@ 261,11 265,13 @@ class Collection(object):
# Just return if we already reached the limit
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])
+ get_val = partial(self.__get_val, key=key)
+ results = sorted(results, key=get_val, reverse=sort[key])
return results[:limit] if isinstance(limit, int) else results
@@ 409,6 409,22 @@ class TestCollection(object):
{'a':1, 'b':'a', '_id':2},
] == self.collection.find(sort={'a':nosqlite.DESCENDING, 'b':nosqlite.DESCENDING})
+ def test_find_with_sort_on_nested_key(self):
+ self.collection.create()
+ self.collection.save({'a':{'b':5}, 'c':'B'})
+ self.collection.save({'a':{'b':9}, 'c':'A'})
+ self.collection.save({'a':{'b':7}, 'c':'C'})
+ assert [
+ {'a':{'b':5}, 'c':'B', '_id':1},
+ {'a':{'b':7}, 'c':'C', '_id':3},
+ {'a':{'b':9}, 'c':'A', '_id':2},
+ ] == self.collection.find(sort={'a.b':nosqlite.ASCENDING})
+ assert [
+ {'a':{'b':9}, 'c':'A', '_id':2},
+ {'a':{'b':7}, 'c':'C', '_id':3},
+ {'a':{'b':5}, 'c':'B', '_id':1},
+ ] == self.collection.find(sort={'a.b':nosqlite.DESCENDING})
+
@mark.parametrize('strdoc,doc', [
('{"foo": "bar"}', {'_id': 1, 'foo': 'bar'}),
(u'{"foo": "☃"}', {'_id': 1, 'foo': u'☃'}),