aggregate.ts 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. import { UnsequencedVideoEvent, VideoEvent, VideoEventsBucketModel, VideoEventType } from './models/VideoEvent'
  2. export class VideoAggregate {
  3. private videoViewsMap: Record<string, number> = {}
  4. private channelViewsMap: Record<string, number> = {}
  5. public videoViews(videoId: string): number {
  6. return this.videoViewsMap[videoId] || 0
  7. }
  8. public channelViews(channelId: string): number {
  9. return this.channelViewsMap[channelId] || 0
  10. }
  11. public async rebuild() {
  12. const aggregation = (await VideoEventsBucketModel.aggregate([
  13. { $unwind: '$events' },
  14. { $group: { _id: null, allEvents: { $push: '$events' } } },
  15. { $project: { events: '$allEvents' } },
  16. ])) as { events: VideoEvent[] }[]
  17. aggregation[0].events.forEach((event) => {
  18. this.applyEvent(event)
  19. })
  20. }
  21. public applyEvent(event: UnsequencedVideoEvent) {
  22. switch (event.eventType) {
  23. case VideoEventType.AddView:
  24. this.applyAddViewEvent(event)
  25. break
  26. default:
  27. console.error(`Parsing unknown video event: ${event.eventType}`)
  28. }
  29. }
  30. private applyAddViewEvent(event: UnsequencedVideoEvent) {
  31. const currentVideoViews = this.videoViewsMap[event.videoId] || 0
  32. const currentChannelViews = this.channelViewsMap[event.channelId] || 0
  33. this.videoViewsMap[event.videoId] = currentVideoViews + 1
  34. this.channelViewsMap[event.channelId] = currentChannelViews + 1
  35. }
  36. }
  37. export const videoAggregate = new VideoAggregate()