今天遇到一个需求,需要计算留存率
留存率怎么计算?
经过查资料得知,其实留存率计算很简单
比如 次留=前一天新增中次日还活跃/前一天新增
其他 3日,周留存,月留存以此类推
数据统计
明白了需求,那么在存储数据结构的时候就有思路了。我目前专门用了一个表来计算留存,表只需要记录几个数据,
/**用来计算留存 */
export interface ModelPlayerLoginRecord {
uid: string;
loginTimestamp: number;
createDayId: string;
}
不错,就是这么简单,只需要记录登录的时间戳和注册的当天的日期Id
我的习惯的dayId格式为“2020-01-01”这样,createDayId需要index,方便加快查询速度。
那么,计算留存的两个数据就很容易得到了。新增直接查dayId就行,活跃的,只需要在dayId查询之后,再加一个条件,loginTimestamp大于要查询当天的开始时间,那么说明他当天就是活跃的
直接上代码:
/**
* 玩家留存计算
* @param day "2020-01-05"
*/
async livePlayerStateCount(day: string) {
//次留,3日流 5日流。。。
let needList = [1, 3, 5, 7, 10, 15, 30]
let beginMoment = moment(day)
let model = ***
let getNewCount = await dao.getCount("ModelPlayerLoginRecord",{createDayId:day})
let getLiveCount = function (dayoff: number): Promise<number> {
return new Promise((resolve, reject) => {
model.find({ createDayId: day })
.where("loginTimestamp").gt(beginMoment.add(dayoff, "day").startOf("day").valueOf())
.count().exec(function (error, res) {
if (!!error) {
console.log("livePlayerStateCount error")
} else {
resolve(res)
}
})
})
}
let newCount = await getNewCount()
let resMap = {}
for (let index = 0; index < needList.length; index++) {
const dayoff = needList[index];
if (newCount > 0) {
let liveCount = await getLiveCount(dayoff)
let liveRate = liveCount / newCount * 100
resMap["day" + dayoff] = liveRate.toFixed(2)
} else {
resMap["day" + dayoff] = 0
}
}
return resMap
}
needList 里面填入需要的几日留存就行了。
这样 例子里面 “2020-01-05” 的次日,3日,5日。。。等的留存率就出来了。
设备留存率,IP留存率,之类的,把uid换成其他的另添加表就行了
另外,有什么不对或者可以优化的地方欢迎大家指正交流