diff --git a/lualib/mongo.lua b/lualib/mongo.lua index 7a8d6eb6..a1a2e11e 100644 --- a/lualib/mongo.lua +++ b/lualib/mongo.lua @@ -279,9 +279,45 @@ function mongo_collection:find(query, selector) __cursor = nil, __document = {}, __flags = 0, + __skip = 0, + __sortquery = nil, + __limit = 0, } , cursor_meta) end +function mongo_cursor:sort(key_list) + self.__sortquery = bson_encode {['$query'] = self.__query, ['$orderby'] = key_list} + return self +end + +function mongo_cursor:skip(amount) + self.__skip = amount + return self +end + +function mongo_cursor:limit(amount) + self.__limit = amount + return self +end + +function mongo_cursor:count(with_limit_and_skip) + local cmd = { + 'count', self.__collection.name, + 'query', self.__query, + } + if with_limit_and_skip then + local len = #cmd + cmd[len+1] = 'limit' + cmd[len+2] = self.__limit + cmd[len+3] = 'skip' + cmd[len+4] = self.__skip + end + local ret = self.__collection.database:runCommand(table.unpack(cmd)) + assert(ret and ret.ok == 1) + return ret.n +end + + -- collection:createIndex({username = 1}, {unique = true}) function mongo_collection:createIndex(keys, option) local name = option.name @@ -348,10 +384,11 @@ function mongo_cursor:hasNext() local sock = conn.__sock local pack if self.__data == nil then - pack = driver.query(request_id, self.__flags, self.__collection.full_name,0,0,self.__query,self.__selector) + local query = self.__sortquery or self.__query + pack = driver.query(request_id, self.__flags, self.__collection.full_name, self.__skip, -self.__limit, query, self.__selector) else if self.__cursor then - pack = driver.more(request_id, self.__collection.full_name,0,self.__cursor) + pack = driver.more(request_id, self.__collection.full_name, -self.__limit, self.__cursor) else -- no more self.__document = nil diff --git a/test/testmongodb.lua b/test/testmongodb.lua index f1fa81e0..d1fed034 100644 --- a/test/testmongodb.lua +++ b/test/testmongodb.lua @@ -43,10 +43,22 @@ function test_find_and_remove() local ret = db[db_name].testdb:safe_insert({test_key = 1}) assert(ret and ret.n == 1) + local ret = db[db_name].testdb:safe_insert({test_key = 2}) + assert(ret and ret.n == 1) + local ret = db[db_name].testdb:findOne({test_key = 1}) assert(ret and ret.test_key == 1) + local ret = db[db_name].testdb:find({test_key = {['$gt'] = 0}}):sort({test_key = -1}):skip(1):limit(1) + assert(ret:count() == 2) + assert(ret:count(true) == 1) + if ret:hasNext() then + ret = ret:next() + end + assert(ret and ret.test_key == 1) + db[db_name].testdb:delete({test_key = 1}) + db[db_name].testdb:delete({test_key = 2}) local ret = db[db_name].testdb:findOne({test_key = 1}) assert(ret == nil)