diff options
Diffstat (limited to 'server/models/view')
-rw-r--r-- | server/models/view/local-video-viewer.ts | 39 |
1 files changed, 27 insertions, 12 deletions
diff --git a/server/models/view/local-video-viewer.ts b/server/models/view/local-video-viewer.ts index 1491acb9e..ad2ad35ca 100644 --- a/server/models/view/local-video-viewer.ts +++ b/server/models/view/local-video-viewer.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import { QueryTypes } from 'sequelize' | 1 | import { QueryTypes } from 'sequelize' |
2 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, HasMany, IsUUID, Model, Table } from 'sequelize-typescript' | 2 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, HasMany, IsUUID, Model, Table } from 'sequelize-typescript' |
3 | import { STATS_TIMESERIE } from '@server/initializers/constants' | ||
4 | import { getActivityStreamDuration } from '@server/lib/activitypub/activity' | 3 | import { getActivityStreamDuration } from '@server/lib/activitypub/activity' |
4 | import { buildGroupByAndBoundaries } from '@server/lib/timeserie' | ||
5 | import { MLocalVideoViewer, MLocalVideoViewerWithWatchSections, MVideo } from '@server/types/models' | 5 | import { MLocalVideoViewer, MLocalVideoViewerWithWatchSections, MVideo } from '@server/types/models' |
6 | import { VideoStatsOverall, VideoStatsRetention, VideoStatsTimeserie, VideoStatsTimeserieMetric, WatchActionObject } from '@shared/models' | 6 | import { VideoStatsOverall, VideoStatsRetention, VideoStatsTimeserie, VideoStatsTimeserieMetric, WatchActionObject } from '@shared/models' |
7 | import { AttributesOnly } from '@shared/typescript-utils' | 7 | import { AttributesOnly } from '@shared/typescript-utils' |
@@ -216,33 +216,48 @@ export class LocalVideoViewerModel extends Model<Partial<AttributesOnly<LocalVid | |||
216 | static async getTimeserieStats (options: { | 216 | static async getTimeserieStats (options: { |
217 | video: MVideo | 217 | video: MVideo |
218 | metric: VideoStatsTimeserieMetric | 218 | metric: VideoStatsTimeserieMetric |
219 | startDate: string | ||
220 | endDate: string | ||
219 | }): Promise<VideoStatsTimeserie> { | 221 | }): Promise<VideoStatsTimeserie> { |
220 | const { video, metric } = options | 222 | const { video, metric } = options |
221 | 223 | ||
224 | const { groupInterval, sqlInterval, startDate, endDate } = buildGroupByAndBoundaries(options.startDate, options.endDate) | ||
225 | |||
222 | const selectMetrics: { [ id in VideoStatsTimeserieMetric ]: string } = { | 226 | const selectMetrics: { [ id in VideoStatsTimeserieMetric ]: string } = { |
223 | viewers: 'COUNT("localVideoViewer"."id")', | 227 | viewers: 'COUNT("localVideoViewer"."id")', |
224 | aggregateWatchTime: 'SUM("localVideoViewer"."watchTime")' | 228 | aggregateWatchTime: 'SUM("localVideoViewer"."watchTime")' |
225 | } | 229 | } |
226 | 230 | ||
227 | const query = `WITH days AS ( ` + | 231 | const query = `WITH "intervals" AS ( |
228 | `SELECT (current_date::timestamp - (serie || ' days')::interval)::timestamptz AS day | 232 | SELECT |
229 | FROM generate_series(0, ${STATS_TIMESERIE.MAX_DAYS - 1}) serie` + | 233 | "time" AS "startDate", "time" + :sqlInterval::interval as "endDate" |
230 | `) ` + | 234 | FROM |
231 | `SELECT days.day AS date, COALESCE(${selectMetrics[metric]}, 0) AS value ` + | 235 | generate_series(:startDate::timestamptz, :endDate::timestamptz, :sqlInterval::interval) serie("time") |
232 | `FROM days ` + | 236 | ) |
233 | `LEFT JOIN "localVideoViewer" ON "localVideoViewer"."videoId" = :videoId ` + | 237 | SELECT "intervals"."startDate" as "date", COALESCE(${selectMetrics[metric]}, 0) AS value |
234 | `AND date_trunc('day', "localVideoViewer"."startDate") = date_trunc('day', days.day) ` + | 238 | FROM |
235 | `GROUP BY day ` + | 239 | intervals |
236 | `ORDER BY day ` | 240 | LEFT JOIN "localVideoViewer" ON "localVideoViewer"."videoId" = :videoId |
241 | AND "localVideoViewer"."startDate" >= "intervals"."startDate" AND "localVideoViewer"."startDate" <= "intervals"."endDate" | ||
242 | GROUP BY | ||
243 | "intervals"."startDate" | ||
244 | ORDER BY | ||
245 | "intervals"."startDate"` | ||
237 | 246 | ||
238 | const queryOptions = { | 247 | const queryOptions = { |
239 | type: QueryTypes.SELECT as QueryTypes.SELECT, | 248 | type: QueryTypes.SELECT as QueryTypes.SELECT, |
240 | replacements: { videoId: video.id } | 249 | replacements: { |
250 | startDate, | ||
251 | endDate, | ||
252 | sqlInterval, | ||
253 | videoId: video.id | ||
254 | } | ||
241 | } | 255 | } |
242 | 256 | ||
243 | const rows = await LocalVideoViewerModel.sequelize.query<any>(query, queryOptions) | 257 | const rows = await LocalVideoViewerModel.sequelize.query<any>(query, queryOptions) |
244 | 258 | ||
245 | return { | 259 | return { |
260 | groupInterval, | ||
246 | data: rows.map(r => ({ | 261 | data: rows.map(r => ({ |
247 | date: r.date, | 262 | date: r.date, |
248 | value: parseInt(r.value) | 263 | value: parseInt(r.value) |