You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 lines
3.5 KiB
Lua

local t_insert = table.insert
local t_remove = table.remove
local t_concat = table.concat
local strbyte = string.byte
local strformat = string.format
local cursor_methods = { }
local cursor_mt = { __index = cursor_methods }
local function new_cursor(col, query, returnfields, num_each_query)
return setmetatable ( {
col = col ;
query = query ;
returnfields = returnfields ;
id = false ;
results = { } ;
done = false ;
i = 0;
limit_n = 0;
num_each = num_each_query;
} , cursor_mt )
end
cursor_mt.__gc = function( self )
self.col:kill_cursors({ self.id })
end
cursor_mt.__tostring = function ( ob )
local t = { }
for i = 1 , 8 do
t_insert(t, strformat("%02x", strbyte(ob.id, i, i)))
end
return "CursorId(" .. t_concat ( t ) .. ")"
end
function cursor_methods:limit(n)
assert(n)
self.limit_n = n
end
--todo
--function cursor_methods:skip(n)
function cursor_methods:sort(field, size)
size = size or 10000
if size < 2 then return nil, "number of object must > 1" end
if not field then return nil, "field should not be nil" end
local key, asc, t
for k,v in pairs(field) do
key = k
asc = v
break
end
if asc ~= 1 and asc ~= -1 then return nil, "order must be 1 or -1" end
local sort_f =
function(a, b)
if not a and not b then return false end
if not a then return true end
if not b then return false end
if not a[key] and not b[key] then return false end
if not a[key] then return true end
if not b[key] then return false end
if asc == 1 then
return a[key] < b[key]
else
return a[key] > b[key]
end
end
if #self.results > self.i then
table.sort(self.results, sort_f)
elseif #self.results == 0 and self.i == 0 then
if self.num_each == 0 and self.limit_n ~= 0 then
size = self.limit_n
elseif self.num_each ~= 0 and self.limit_n == 0 then
size = self.num_each
else
size = (self.num_each < self.limit_n
and self.num_each) or self.limit_n
end
self.id, self.results, t = self.col:query(self.query,
self.returnfields, self.i, size)
table.sort(self.results, sort_f)
else
return nil, "sort must be an array"
end
return self.results
end
function cursor_methods:next()
if self.limit_n > 0 and self.i >= self.limit_n then return nil end
local v = self.results [ self.i + 1 ]
if v ~= nil then
self.i = self.i + 1
self.results [ self.i ] = nil
return self.i , v
end
if self.done then return nil end
local t
if not self.id then
self.id, self.results, t = self.col:query(self.query,
self.returnfields, self.i, self.num_each)
if self.id == "\0\0\0\0\0\0\0\0" then
self.done = true
end
else
self.id, self.results, t = self.col:getmore(self.id,
self.num_each, self.i)
if self.id == "\0\0\0\0\0\0\0\0" then
self.done = true
elseif t.CursorNotFound then
self.id = false
end
end
return self:next ( )
end
function cursor_methods:pairs( )
return self.next, self
end
return new_cursor