Last active
July 12, 2018 13:23
-
-
Save davidlondono/10924678cf6307960583f8c080c5972c to your computer and use it in GitHub Desktop.
Paginate Redis
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Created by david on 9/27/16. | |
*/ | |
import redis from './connectionRedis'; | |
import ZList from './zlist'; | |
import Promise from 'bluebird'; | |
export default class ModelList { | |
constructor(name) { | |
this.name = name; | |
this.list = new ZList(name); | |
} | |
plugin(plugin, opts) { | |
plugin(this, opts); | |
} | |
getScoreById(id) { | |
return redis.zscore(`${this.name}`, id); | |
} | |
memberisOfType({ member, type }) { | |
return redis.sismember(`${this.name}:${type}`, member); | |
} | |
add({ type, id, score }) { | |
return Promise.all([ | |
this.list.add({ score, member: id }), | |
redis.sadd(`${this.name}:${type}`, id), | |
]); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Created by david on 9/27/16. | |
*/ | |
/** | |
* | |
* @param {ModelList} model | |
*/ | |
import Promise from 'bluebird'; | |
export default (model) => { | |
model.paginate = async function({ | |
sinceId, maxId, limit = 1, select, where = {}, | |
keyPaginated = '_id', reverse = false, | |
filter, | |
} = {}, callback) { | |
const range = {}; | |
if (sinceId) { | |
range.min = await model.getScoreById(sinceId); | |
} | |
if (maxId) { | |
range.max = await model.getScoreById(maxId); | |
} | |
const limitRange = { | |
count: limit + 1, | |
}; | |
const objectsFirstFound = await model.list.rangeByScore({ | |
range, | |
reverse, limit: limitRange }); | |
if (!objectsFirstFound.length) { | |
return { | |
objectsFirstFound, | |
}; | |
} | |
let objects = []; | |
if (filter) { | |
let objToFilter = objectsFirstFound; | |
do { | |
const objectsFiltered = await Promise.resolve(objToFilter).filter(filter); | |
objects = objects.concat(objectsFiltered); | |
// console.log('after filter', objectsFirstFound); | |
const lastScore = objToFilter[objToFilter.length - 1].score; | |
limitRange.count -= objectsFiltered.length; | |
range.max = parseInt(lastScore, 10) - 1; | |
objToFilter = await model.list.rangeByScore({ | |
range, | |
reverse, limit: limitRange }); | |
} while (limitRange.count > 0 && objToFilter.length > 0); | |
} | |
let nextMaxId; | |
if (objects.length >= limit) { | |
const last = objectsFirstFound.pop(); | |
nextMaxId = last.member; | |
} | |
return { | |
objects, | |
nextMaxId, | |
}; | |
}; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Created by James on 26/09/16. | |
*/ | |
import redis from './connectionRedis'; | |
/* import _debug from 'debug'; | |
const debug = _debug('feedModule:zlist');*/ | |
function castToObject(array) { | |
const objects = []; | |
for (let i = 0; i < array.length; i += 2) { | |
objects.push( | |
{ member: array[i], | |
score: array[i + 1] }); | |
} | |
return objects; | |
} | |
class ZList { | |
constructor(name) { | |
this.name = name; | |
} | |
async add({ score, member }) { | |
return await redis.zadd(this.name, score, member); | |
} | |
async remove(member) { | |
return await redis.zrem(this.name, member); | |
} | |
async scan(cursor) { | |
const [pointer, listOfKeys] = await redis.zscan(this.name, cursor); | |
return { | |
pointer, | |
data: castToObject(listOfKeys), | |
}; | |
} | |
async rangeByScore({ | |
range: { min = '-inf', max = '+inf' } = {}, | |
limit, reverse = false } = {}) { | |
const redisArgs = []; | |
if (limit) { | |
const { offset = 0, count = 1 } = limit; | |
redisArgs.push('LIMIT'); | |
redisArgs.push(offset); | |
redisArgs.push(count); | |
} | |
redisArgs.push('WITHSCORES'); | |
let promiseFind; | |
if (reverse) { | |
promiseFind = redis.zrevrangebyscore(this.name, max, min, ...redisArgs); | |
} else { | |
promiseFind = redis.zrangebyscore(this.name, min, max, ...redisArgs); | |
} | |
const memberArrays = await promiseFind; | |
return castToObject(memberArrays); | |
} | |
} | |
export default ZList; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment