eventResult.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /**
  2. * @class EventResult 事件结果统计
  3. */
  4. const BaseMod = require('./base')
  5. const Platform = require('./platform')
  6. const Channel = require('./channel')
  7. const Version = require('./version')
  8. const EventLog = require('./eventLog')
  9. const {
  10. DateTime
  11. } = require('../lib')
  12. module.exports = class EventResult extends BaseMod {
  13. constructor() {
  14. super()
  15. this.tableName = 'event-result'
  16. this.platforms = []
  17. this.channels = []
  18. this.versions = []
  19. }
  20. /**
  21. * 事件数据统计
  22. * @param {String} type 统计类型 hour:实时统计 day:按天统计,week:按周统计 month:按月统计
  23. * @param {Date|Time} date 指定日期或时间戳
  24. * @param {Boolean} reset 是否重置,为ture时会重置该批次数据
  25. */
  26. async stat(type, date, reset) {
  27. const allowedType = ['day']
  28. if (!allowedType.includes(type)) {
  29. return {
  30. code: 1002,
  31. msg: 'This type is not allowed'
  32. }
  33. }
  34. this.fillType = type
  35. const dateTime = new DateTime()
  36. const dateDimension = dateTime.getTimeDimensionByType(type, -1, date)
  37. this.startTime = dateDimension.startTime
  38. this.endTime = dateDimension.endTime
  39. if (this.debug) {
  40. console.log('dimension time', this.startTime + '--' + this.endTime)
  41. }
  42. // 查看当前时间段日志是否已存在,防止重复生成
  43. if (!reset) {
  44. const checkRes = await this.getCollection(this.tableName).where({
  45. start_time: this.startTime,
  46. end_time: this.endTime
  47. }).get()
  48. if (checkRes.data.length > 0) {
  49. console.log('event log have existed')
  50. return {
  51. code: 1003,
  52. msg: 'This log have existed'
  53. }
  54. }
  55. } else {
  56. const delRes = await this.delete(this.tableName, {
  57. start_time: this.startTime,
  58. end_time: this.endTime
  59. })
  60. console.log('delete old data result:', JSON.stringify(delRes))
  61. }
  62. // 数据获取
  63. this.eventLog = new EventLog()
  64. const statRes = await this.aggregate(this.eventLog.tableName, {
  65. project: {
  66. appid: 1,
  67. version: 1,
  68. platform: 1,
  69. channel: 1,
  70. event_key: 1,
  71. device_id: 1,
  72. create_time: 1
  73. },
  74. match: {
  75. create_time: {
  76. $gte: this.startTime,
  77. $lte: this.endTime
  78. }
  79. },
  80. group: {
  81. _id: {
  82. appid: '$appid',
  83. version: '$version',
  84. platform: '$platform',
  85. channel: '$channel',
  86. event_key: '$event_key'
  87. },
  88. event_count: {
  89. $sum: 1
  90. }
  91. },
  92. sort: {
  93. event_count: 1
  94. },
  95. getAll: true
  96. })
  97. let res = {
  98. code: 0,
  99. msg: 'success'
  100. }
  101. if (this.debug) {
  102. console.log('statRes', JSON.stringify(statRes))
  103. }
  104. if (statRes.data.length > 0) {
  105. this.fillData = []
  106. for (const i in statRes.data) {
  107. await this.fill(statRes.data[i])
  108. }
  109. if (this.fillData.length > 0) {
  110. res = await this.batchInsert(this.tableName, this.fillData)
  111. }
  112. }
  113. return res
  114. }
  115. /**
  116. * 事件统计数据填充
  117. * @param {Object} data 数据集合
  118. */
  119. async fill(data) {
  120. // 平台信息
  121. let platformInfo = null
  122. if (this.platforms && this.platforms[data._id.platform]) {
  123. //暂存下数据,减少读库
  124. platformInfo = this.platforms[data._id.platform]
  125. } else {
  126. const platform = new Platform()
  127. platformInfo = await platform.getPlatformAndCreate(data._id.platform, null)
  128. if (!platformInfo || platformInfo.length === 0) {
  129. platformInfo._id = ''
  130. }
  131. this.platforms[data._id.platform] = platformInfo
  132. if (this.debug) {
  133. console.log('platformInfo', JSON.stringify(platformInfo))
  134. }
  135. }
  136. // 渠道信息
  137. let channelInfo = null
  138. const channelKey = data._id.appid + '_' + platformInfo._id + '_' + data._id.channel
  139. if (this.channels && this.channels[channelKey]) {
  140. channelInfo = this.channels[channelKey]
  141. } else {
  142. const channel = new Channel()
  143. channelInfo = await channel.getChannelAndCreate(data._id.appid, platformInfo._id, data._id.channel)
  144. if (!channelInfo || channelInfo.length === 0) {
  145. channelInfo._id = ''
  146. }
  147. this.channels[channelKey] = channelInfo
  148. if (this.debug) {
  149. console.log('channelInfo', JSON.stringify(channelInfo))
  150. }
  151. }
  152. // 版本信息
  153. let versionInfo = null
  154. const versionKey = data._id.appid + '_' + data._id.platform + '_' + data._id.version
  155. if (this.versions && this.versions[versionKey]) {
  156. versionInfo = this.versions[versionKey]
  157. } else {
  158. const version = new Version()
  159. versionInfo = await version.getVersionAndCreate(data._id.appid, data._id.platform, data._id.version)
  160. if (!versionInfo || versionInfo.length === 0) {
  161. versionInfo._id = ''
  162. }
  163. this.versions[versionKey] = versionInfo
  164. if (this.debug) {
  165. console.log('versionInfo', JSON.stringify(versionInfo))
  166. }
  167. }
  168. const matchCondition = data._id
  169. Object.assign(matchCondition, {
  170. create_time: {
  171. $gte: this.startTime,
  172. $lte: this.endTime
  173. }
  174. })
  175. if (this.debug) {
  176. console.log('matchCondition', JSON.stringify(matchCondition))
  177. }
  178. // 触发事件设备数统计
  179. const statEventDeviceRes = await this.aggregate(this.eventLog.tableName, {
  180. project: {
  181. appid: 1,
  182. version: 1,
  183. platform: 1,
  184. channel: 1,
  185. event_key: 1,
  186. device_id: 1,
  187. create_time: 1
  188. },
  189. match: matchCondition,
  190. group: [{
  191. _id: {
  192. device_id: '$device_id'
  193. }
  194. }, {
  195. _id: {},
  196. total_devices: {
  197. $sum: 1
  198. }
  199. }]
  200. })
  201. let eventDeviceCount = 0
  202. if (statEventDeviceRes.data.length > 0) {
  203. eventDeviceCount = statEventDeviceRes.data[0].total_devices
  204. }
  205. // 触发事件用户数统计
  206. const statEventUserRes = await this.aggregate(this.eventLog.tableName, {
  207. project: {
  208. appid: 1,
  209. version: 1,
  210. platform: 1,
  211. channel: 1,
  212. event_key: 1,
  213. uid: 1,
  214. create_time: 1
  215. },
  216. match: {
  217. ...matchCondition,
  218. uid: {
  219. $ne: ''
  220. }
  221. },
  222. group: [{
  223. _id: {
  224. uid: '$uid'
  225. }
  226. }, {
  227. _id: {},
  228. total_users: {
  229. $sum: 1
  230. }
  231. }]
  232. })
  233. let eventUserCount = 0
  234. if (statEventUserRes.data.length > 0) {
  235. eventUserCount = statEventUserRes.data[0].total_users
  236. }
  237. const datetime = new DateTime()
  238. const insertParams = {
  239. appid: data._id.appid,
  240. platform_id: platformInfo._id,
  241. channel_id: channelInfo._id,
  242. version_id: versionInfo._id,
  243. event_key: data._id.event_key,
  244. event_count: data.event_count,
  245. device_count: eventDeviceCount,
  246. user_count: eventUserCount,
  247. dimension: this.fillType,
  248. stat_date: datetime.getDate('Ymd', this.startTime),
  249. start_time: this.startTime,
  250. end_time: this.endTime
  251. }
  252. this.fillData.push(insertParams)
  253. return insertParams
  254. }
  255. }