redis 分頁查詢

算法: redis

容器使用的是zset,由於當zset中全部的分值都爲0時集合將按ascii碼排序。因此利用這點只要找出其範圍再 算法

使用zrange獲取就好了。取得該範圍的方式是經過在集合中插入兩個搜索關鍵字的臨界值,如搜索abc,那麼這個 lua

臨界值爲abb{ 和abc{ 。將其插入到集合中再搜索出基位置。最後將其刪除(參考:<<redis in action>>) 3d

下面是分頁lua腳本: code

--[[
zset 分頁查詢: 
 格式: <zsetKey> <searchKey> <pageNo> <pageSize>
 參數說明:{
	zsetKey   :有序集鍵 key1   
	searchKey : 查詢內容 argv1
	pageNo    :當前頁號(默認爲1) argv2
    pageSize  :頁面大小(默認爲15) argv3
 }
 示例: evalsha 232fd51614574cf0867b83d384a5e898cfd24e5a 1 my:zset abc
]]
local zsetKey,searchKey,pageNo,pageSize = KEYS[1],ARGV[1],tonumber(ARGV[2]),tonumber(ARGV[3])
local content = ",-/0123456789@_abcdefghijklmnopqrstuvwxyz{"

if(not zsetKey) then return {} end
if(not pageNo or pageNo < 1) then pageNo = 1 end
if(not pageSize or pageSize < 1) then pageSize = 15 end

local recTotal = redis.call('zcard',zsetKey)
if(recTotal == 0) then return {} end  --空集合

--找出查詢關鍵字在zset中的位置
local function getRange(searchKey)
	local lastChar = string.sub(searchKey,-1,-1)
    local temp = string.find(content,lastChar)-1
	local startStr = string.sub(searchKey,1,-2)..string.sub(content,temp,temp)..string.sub(content,-1,-1)
	local endStr = searchKey..string.sub(content,-1,-1)
	redis.call('zadd',zsetKey,0,startStr)
	redis.call('zadd',zsetKey,0,endStr)
    local starp1,starp2 = redis.call('zrank',zsetKey,startStr) , redis.call('zrank',zsetKey,endStr)
    redis.call('zrem',zsetKey,startStr)
    redis.call('zrem',zsetKey,endStr)
	return starp1,starp2-2
end

local startPosition,endPosition = 0,recTotal
if(searchKey ~= "") then
	startPosition,endPosition = getRange(searchKey);
end

startPosition = startPosition + (pageNo-1)*pageSize
endPosition = math.min(startPosition + pageSize-1,endPosition)


if(startPosition > recTotal or endPosition < 0) then return {} end --沒有找到要查詢的結果

return redis.call('zrange',zsetKey,startPosition,endPosition)



--[[
zset 查詢總數: 
 格式: <zsetKey> <searchKey> 
 參數說明:{
	zsetKey   :有序集鍵 key1   
	searchKey : 查詢內容 argv1
 }
 示例: evalsha 232fd51614574cf0867b83d384a5e898cfd24e5a 1 my:zset abc
]]
local zsetKey,searchKey = KEYS[1],ARGV[1]
local content = ",-/0123456789@_abcdefghijklmnopqrstuvwxyz{"

if(not zsetKey) then return 0 end
local recTotal = redis.call('zcard',zsetKey)
if(searchKey == "") then return recTotal end  

--找出查詢關鍵字在zset中的位置
local function getRange(searchKey)
	local lastChar = string.sub(searchKey,-1,-1)
    local temp = string.find(content,lastChar)-1
	local startStr = string.sub(searchKey,1,-2)..string.sub(content,temp,temp)..string.sub(content,-1,-1)
	local endStr = searchKey..string.sub(content,-1,-1)
	redis.call('zadd',zsetKey,0,startStr)
	redis.call('zadd',zsetKey,0,endStr)
    local starp1,starp2 = redis.call('zrank',zsetKey,startStr) , redis.call('zrank',zsetKey,endStr)
    redis.call('zrem',zsetKey,startStr)
    redis.call('zrem',zsetKey,endStr)
	return starp1,starp2-2
end

local startPosition,endPosition = getRange(searchKey);

if(startPosition > recTotal or endPosition < 0) then return 0 end --沒有找到要查詢的結果

return endPosition - startPosition + 1;



上面只支持英文查詢(小寫) 排序

相關文章
相關標籤/搜索