123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491 |
- /**
- * 设备/用户忠诚度(粘性)统计模型
- */
- const BaseMod = require('./base')
- const Platform = require('./platform')
- const Channel = require('./channel')
- const Version = require('./version')
- const SessionLog = require('./sessionLog')
- const UserSessionLog = require('./userSessionLog')
- const {
- DateTime
- } = require('../lib')
- module.exports = class Loyalty extends BaseMod {
- constructor() {
- super()
- this.tableName = 'loyalty-result'
- this.platforms = []
- this.channels = []
- this.versions = []
- }
- /**
- * 设备/用户忠诚度(粘性)统计
- * @param {String} type 统计类型 hour:实时统计 day:按天统计,week:按周统计 month:按月统计
- * @param {Date|Time} date 指定日期或时间戳
- * @param {Boolean} reset 是否重置,为ture时会重置该批次数据
- */
- async stat(type, date, reset) {
- const allowedType = ['day']
- if (!allowedType.includes(type)) {
- return {
- code: 1002,
- msg: 'This type is not allowed'
- }
- }
- this.fillType = type
- const dateTime = new DateTime()
- const dateDimension = dateTime.getTimeDimensionByType(type, -1, date)
- this.startTime = dateDimension.startTime
- this.endTime = dateDimension.endTime
- if (this.debug) {
- console.log('this time', dateTime.getTime())
- console.log('dimension time', this.startTime + '--' + this.endTime)
- }
- // 查看当前时间段日志是否已存在,防止重复生成
- if (!reset) {
- const checkRes = await this.getCollection(this.tableName).where({
- start_time: this.startTime,
- end_time: this.endTime
- }).get()
- if (checkRes.data.length > 0) {
- console.log('loyalty log have existed')
- return {
- code: 1003,
- msg: 'This log have existed'
- }
- }
- } else {
- const delRes = await this.delete(this.tableName, {
- start_time: this.startTime,
- end_time: this.endTime
- })
- console.log('delete old data result:', JSON.stringify(delRes))
- }
- // 数据获取
- this.sessionLog = new SessionLog()
- const statRes = await this.aggregate(this.sessionLog.tableName, {
- project: {
- appid: 1,
- version: 1,
- platform: 1,
- channel: 1,
- page_count: 1,
- duration: 1,
- create_time: 1
- },
- match: {
- create_time: {
- $gte: this.startTime,
- $lte: this.endTime
- }
- },
- group: {
- _id: {
- appid: '$appid',
- version: '$version',
- platform: '$platform',
- channel: '$channel'
- },
- page_count_sum: {
- $sum: '$page_count'
- },
- duration_sum: {
- $sum: '$duration'
- }
- },
- sort: {
- page_count_sum: 1,
- duration_sum: 1
- },
- getAll: true
- })
- let res = {
- code: 0,
- msg: 'success'
- }
- if (this.debug) {
- console.log('statRes', JSON.stringify(statRes))
- }
- if (statRes.data.length > 0) {
- this.fillData = []
- for (const i in statRes.data) {
- await this.fill(statRes.data[i])
- }
- if (this.fillData.length > 0) {
- res = await this.batchInsert(this.tableName, this.fillData)
- }
- }
- return res
- }
- /**
- * 设备/用户忠诚度(粘性)数据填充
- * @param {Object} data 数据集合
- */
- async fill(data) {
- // 平台信息
- let platformInfo = null
- if (this.platforms && this.platforms[data._id.platform]) {
- platformInfo = this.platforms[data._id.platform]
- } else {
- const platform = new Platform()
- platformInfo = await platform.getPlatformAndCreate(data._id.platform, null)
- if (!platformInfo || platformInfo.length === 0) {
- platformInfo._id = ''
- }
- this.platforms[data._id.platform] = platformInfo
- if (this.debug) {
- console.log('platformInfo', JSON.stringify(platformInfo))
- }
- }
- // 渠道信息
- let channelInfo = null
- const channelKey = data._id.appid + '_' + platformInfo._id + '_' + data._id.channel
- if (this.channels && this.channels[channelKey]) {
- channelInfo = this.channels[channelKey]
- } else {
- const channel = new Channel()
- channelInfo = await channel.getChannelAndCreate(data._id.appid, platformInfo._id, data._id.channel)
- if (!channelInfo || channelInfo.length === 0) {
- channelInfo._id = ''
- }
- this.channels[channelKey] = channelInfo
- if (this.debug) {
- console.log('channelInfo', JSON.stringify(channelInfo))
- }
- }
- // 版本信息
- let versionInfo = null
- const versionKey = data._id.appid + '_' + data._id.platform + '_' + data._id.version
- if (this.versions && this.versions[versionKey]) {
- versionInfo = this.versions[versionKey]
- } else {
- const version = new Version()
- versionInfo = await version.getVersionAndCreate(data._id.appid, data._id.platform, data._id.version)
- if (!versionInfo || versionInfo.length === 0) {
- versionInfo._id = ''
- }
- this.versions[versionKey] = versionInfo
- if (this.debug) {
- console.log('versionInfo', JSON.stringify(versionInfo))
- }
- }
- // 访问深度-用户数统计和访问次数
- const pageMark = [1, 2, 3, 4, [5, 10], [10]]
- const matchCondition = Object.assign(data._id, {
- create_time: {
- $gte: this.startTime,
- $lte: this.endTime
- }
- })
- const visitDepthData = {
- visit_devices: {},
- visit_users: {},
- visit_times: {}
- }
-
- const userSessionLog = new UserSessionLog()
- //根据各访问页面数区间统计
- for (const pi in pageMark) {
- let pageMarkCondition = {
- page_count: pageMark[pi]
- }
- if (Array.isArray(pageMark[pi])) {
- if (pageMark[pi].length === 2) {
- pageMarkCondition = {
- page_count: {
- $gte: pageMark[pi][0],
- $lte: pageMark[pi][1]
- }
- }
- } else {
- pageMarkCondition = {
- page_count: {
- $gt: pageMark[pi][0]
- }
- }
- }
- }
- // 访问次数(会话次数)统计
- const searchCondition = {
- ...matchCondition,
- ...pageMarkCondition
- }
- const vistRes = await this.aggregate(this.sessionLog.tableName, {
- project: {
- appid: 1,
- version: 1,
- platform: 1,
- channel: 1,
- page_count: 1,
- create_time: 1
- },
- match: searchCondition,
- group: {
- _id: {},
- total_visits: {
- $sum: 1
- }
- }
- })
- if (this.debug) {
- console.log('vistResCondtion', JSON.stringify(searchCondition))
- console.log('vistRes', JSON.stringify(vistRes))
- }
- let vistCount = 0
- if (vistRes.data.length > 0) {
- vistCount = vistRes.data[0].total_visits
- }
-
- // 设备数统计
- const deviceRes = await this.aggregate(this.sessionLog.tableName, {
- project: {
- appid: 1,
- version: 1,
- platform: 1,
- channel: 1,
- page_count: 1,
- create_time: 1,
- device_id: 1
- },
- match: searchCondition,
- group: [{
- _id: {
- device_id: '$device_id'
- }
- }, {
- _id: {},
- total_devices: {
- $sum: 1
- }
- }]
- })
-
- if (this.debug) {
- console.log('searchCondition', JSON.stringify(searchCondition))
- console.log('deviceRes', JSON.stringify(deviceRes))
- }
-
- let deviceCount = 0
- if (deviceRes.data.length > 0) {
- deviceCount = deviceRes.data[0].total_devices
- }
- // 用户数统计
- const userRes = await this.aggregate(userSessionLog.tableName, {
- project: {
- appid: 1,
- version: 1,
- platform: 1,
- channel: 1,
- page_count: 1,
- create_time: 1,
- uid: 1
- },
- match: searchCondition,
- group: [{
- _id: {
- uid: '$uid'
- }
- }, {
- _id: {},
- total_users: {
- $sum: 1
- }
- }]
- })
- if (this.debug) {
- console.log('userResCondtion', JSON.stringify(searchCondition))
- console.log('userRes', JSON.stringify(userRes))
- }
- let userCount = 0
- if (userRes.data.length > 0) {
- userCount = userRes.data[0].total_users
- }
- const pageKey = 'p_' + (Array.isArray(pageMark[pi]) ? pageMark[pi][0] : pageMark[pi])
- visitDepthData.visit_devices[pageKey] = deviceCount
- visitDepthData.visit_users[pageKey] = userCount
- visitDepthData.visit_times[pageKey] = vistCount
- }
- // 访问时长-用户数统计和访问次数
- const durationMark = [
- [0, 2],
- [3, 5],
- [6, 10],
- [11, 20],
- [21, 30],
- [31, 50],
- [51, 100],
- [100]
- ]
- const durationData = {
- visit_devices: {},
- visit_users: {},
- visit_times: {}
- }
- //根据各访问时长区间统计
- for (const di in durationMark) {
- let durationMarkCondition = {
- duration: durationMark[di]
- }
- if (Array.isArray(durationMark[di])) {
- if (durationMark[di].length === 2) {
- durationMarkCondition = {
- duration: {
- $gte: durationMark[di][0],
- $lte: durationMark[di][1]
- }
- }
- } else {
- durationMarkCondition = {
- duration: {
- $gt: durationMark[di][0]
- }
- }
- }
- }
- // 访问次数(会话次数)统计
- const searchCondition = {
- ...matchCondition,
- ...durationMarkCondition
- }
- if (this.debug) {
- console.log('searchCondition', JSON.stringify(searchCondition))
- }
- const vistRes = await this.aggregate(this.sessionLog.tableName, {
- project: {
- appid: 1,
- version: 1,
- platform: 1,
- channel: 1,
- duration: 1,
- create_time: 1
- },
- match: searchCondition,
- group: {
- _id: {},
- total_visits: {
- $sum: 1
- }
- }
- })
- if (this.debug) {
- console.log('vistRes', JSON.stringify(vistRes))
- }
- let vistCount = 0
- if (vistRes.data.length > 0) {
- vistCount = vistRes.data[0].total_visits
- }
-
- // 设备数统计
- const deviceRes = await this.aggregate(this.sessionLog.tableName, {
- project: {
- appid: 1,
- version: 1,
- platform: 1,
- channel: 1,
- device_id: 1,
- duration: 1,
- create_time: 1
- },
- match: searchCondition,
- group: [{
- _id: {
- device_id: '$device_id'
- }
- }, {
- _id: {},
- total_devices: {
- $sum: 1
- }
- }]
- })
-
- if (this.debug) {
- console.log('userRes', JSON.stringify(deviceRes))
- }
-
- let deviceCount = 0
- if (deviceRes.data.length > 0) {
- deviceCount = deviceRes.data[0].total_devices
- }
-
- // 用户数统计
- const userRes = await this.aggregate(userSessionLog.tableName, {
- project: {
- appid: 1,
- version: 1,
- platform: 1,
- channel: 1,
- uid: 1,
- duration: 1,
- create_time: 1
- },
- match: searchCondition,
- group: [{
- _id: {
- uid: '$uid'
- }
- }, {
- _id: {},
- total_users: {
- $sum: 1
- }
- }]
- })
- if (this.debug) {
- console.log('userRes', JSON.stringify(userRes))
- }
- let userCount = 0
- if (userRes.data.length > 0) {
- userCount = userRes.data[0].total_users
- }
- const pageKey = 's_' + (Array.isArray(durationMark[di]) ? durationMark[di][0] : durationMark[di])
- durationData.visit_devices[pageKey] = deviceCount
- durationData.visit_users[pageKey] = userCount
- durationData.visit_times[pageKey] = vistCount
- }
- // 数据填充
- const datetime = new DateTime()
- const insertParams = {
- appid: data._id.appid,
- platform_id: platformInfo._id,
- channel_id: channelInfo._id,
- version_id: versionInfo._id,
- visit_depth_data: visitDepthData,
- duration_data: durationData,
- stat_date: datetime.getDate('Ymd', this.startTime),
- start_time: this.startTime,
- end_time: this.endTime
- }
- this.fillData.push(insertParams)
- return insertParams
- }
- }
|