1
0
Fork 0
mirror of https://github.com/Chocobozzz/PeerTube.git synced 2025-10-05 02:39:33 +02:00

modularize abstract video list header and implement video hotness recommendation variant

This commit is contained in:
Rigel Kent 2021-01-22 00:12:44 +01:00 committed by Chocobozzz
parent 7a4994873c
commit 5bcbcbe338
34 changed files with 396 additions and 63 deletions

View file

@ -32,6 +32,8 @@ export type BuildVideosQueryOptions = {
videoPlaylistId?: number
trendingDays?: number
hot?: boolean
user?: MUserAccountId
historyOfUser?: MUserId
@ -239,14 +241,46 @@ function buildListQuery (model: typeof Model, options: BuildVideosQueryOptions)
}
}
// We don't exclude results in this if so if we do a count we don't need to add this complex clauses
// We don't exclude results in this so if we do a count we don't need to add this complex clause
if (options.trendingDays && options.isCount !== true) {
const viewsGteDate = new Date(new Date().getTime() - (24 * 3600 * 1000) * options.trendingDays)
joins.push('LEFT JOIN "videoView" ON "video"."id" = "videoView"."videoId" AND "videoView"."startDate" >= :viewsGteDate')
replacements.viewsGteDate = viewsGteDate
attributes.push('COALESCE(SUM("videoView"."views"), 0) AS "videoViewsSum"')
attributes.push('COALESCE(SUM("videoView"."views"), 0) AS "score"')
group = 'GROUP BY "video"."id"'
} else if (options.hot && options.isCount !== true) {
/**
* "Hotness" is a measure based on absolute view/comment/like/dislike numbers,
* with fixed weights only applied to their log values.
*
* This algorithm gives little chance for an old video to have a good score,
* for which recent spikes in interactions could be a sign of "hotness" and
* justify a better score. However there are multiple ways to achieve that
* goal, which is left for later. Yes, this is a TODO :)
*
* note: weights and base score are in number of half-days.
* see https://github.com/reddit-archive/reddit/blob/master/r2/r2/lib/db/_sorts.pyx#L47-L58
*/
const weights = {
like: 3,
dislike: 3,
view: 1 / 12,
comment: 6
}
joins.push('LEFT JOIN "videoComment" ON "video"."id" = "videoComment"."videoId"')
attributes.push(
`LOG(GREATEST(1, "video"."likes" - 1)) * ${weights.like} ` + // likes (+)
`- LOG(GREATEST(1, "video"."dislikes" - 1)) * ${weights.dislike} ` + // dislikes (-)
`+ LOG("video"."views" + 1) * ${weights.view} ` + // views (+)
`+ LOG(GREATEST(1, COUNT(DISTINCT "videoComment"."id") - 1)) * ${weights.comment} ` + // comments (+)
'+ (SELECT EXTRACT(epoch FROM "video"."publishedAt") / 47000) ' + // base score (in number of half-days)
'AS "score"'
)
group = 'GROUP BY "video"."id"'
}
@ -372,8 +406,8 @@ function buildOrder (value: string) {
if (field.toLowerCase() === 'random') return 'ORDER BY RANDOM()'
if (field.toLowerCase() === 'trending') { // Sort by aggregation
return `ORDER BY "videoViewsSum" ${direction}, "video"."views" ${direction}`
if ([ 'trending', 'hot' ].includes(field.toLowerCase())) { // Sort by aggregation
return `ORDER BY "score" ${direction}, "video"."views" ${direction}`
}
let firstSort: string