aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models
diff options
context:
space:
mode:
Diffstat (limited to 'server/models')
-rw-r--r--server/models/video/tag.ts24
-rw-r--r--server/models/video/video.ts23
2 files changed, 45 insertions, 2 deletions
diff --git a/server/models/video/tag.ts b/server/models/video/tag.ts
index 6d79a5575..e39a418cd 100644
--- a/server/models/video/tag.ts
+++ b/server/models/video/tag.ts
@@ -1,10 +1,11 @@
1import * as Bluebird from 'bluebird' 1import * as Bluebird from 'bluebird'
2import { Transaction } from 'sequelize' 2import * as Sequelize from 'sequelize'
3import { AllowNull, BelongsToMany, Column, CreatedAt, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' 3import { AllowNull, BelongsToMany, Column, CreatedAt, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
4import { isVideoTagValid } from '../../helpers/custom-validators/videos' 4import { isVideoTagValid } from '../../helpers/custom-validators/videos'
5import { throwIfNotValid } from '../utils' 5import { throwIfNotValid } from '../utils'
6import { VideoModel } from './video' 6import { VideoModel } from './video'
7import { VideoTagModel } from './video-tag' 7import { VideoTagModel } from './video-tag'
8import { VideoPrivacy, VideoState } from '../../../shared/models/videos'
8 9
9@Table({ 10@Table({
10 tableName: 'tag', 11 tableName: 'tag',
@@ -36,7 +37,7 @@ export class TagModel extends Model<TagModel> {
36 }) 37 })
37 Videos: VideoModel[] 38 Videos: VideoModel[]
38 39
39 static findOrCreateTags (tags: string[], transaction: Transaction) { 40 static findOrCreateTags (tags: string[], transaction: Sequelize.Transaction) {
40 if (tags === null) return [] 41 if (tags === null) return []
41 42
42 const tasks: Bluebird<TagModel>[] = [] 43 const tasks: Bluebird<TagModel>[] = []
@@ -59,4 +60,23 @@ export class TagModel extends Model<TagModel> {
59 60
60 return Promise.all(tasks) 61 return Promise.all(tasks)
61 } 62 }
63
64 // threshold corresponds to how many video the field should have to be returned
65 static getRandomSamples (threshold: number, count: number): Bluebird<string[]> {
66 const query = 'SELECT tag.name FROM tag ' +
67 'INNER JOIN "videoTag" ON "videoTag"."tagId" = tag.id ' +
68 'INNER JOIN video ON video.id = "videoTag"."videoId" ' +
69 'WHERE video.privacy = $videoPrivacy AND video.state = $videoState ' +
70 'GROUP BY tag.name HAVING COUNT(tag.name) >= $threshold ' +
71 'ORDER BY random() ' +
72 'LIMIT $count'
73
74 const options = {
75 bind: { threshold, count, videoPrivacy: VideoPrivacy.PUBLIC, videoState: VideoState.PUBLISHED },
76 type: Sequelize.QueryTypes.SELECT
77 }
78
79 return TagModel.sequelize.query(query, options)
80 .then(data => data.map(d => d.name))
81 }
62} 82}
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index 3410833c8..695990b17 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -1083,6 +1083,29 @@ export class VideoModel extends Model<VideoModel> {
1083 }) 1083 })
1084 } 1084 }
1085 1085
1086 // threshold corresponds to how many video the field should have to be returned
1087 static getRandomFieldSamples (field: 'category' | 'channelId', threshold: number, count: number) {
1088 const query: IFindOptions<VideoModel> = {
1089 attributes: [ field ],
1090 limit: count,
1091 group: field,
1092 having: Sequelize.where(Sequelize.fn('COUNT', Sequelize.col(field)), {
1093 [Sequelize.Op.gte]: threshold
1094 }) as any, // FIXME: typings
1095 where: {
1096 [field]: {
1097 [Sequelize.Op.not]: null,
1098 },
1099 privacy: VideoPrivacy.PUBLIC,
1100 state: VideoState.PUBLISHED
1101 },
1102 order: [ this.sequelize.random() ]
1103 }
1104
1105 return VideoModel.findAll(query)
1106 .then(rows => rows.map(r => r[field]))
1107 }
1108
1086 private static buildActorWhereWithFilter (filter?: VideoFilter) { 1109 private static buildActorWhereWithFilter (filter?: VideoFilter) {
1087 if (filter && filter === 'local') { 1110 if (filter && filter === 'local') {
1088 return { 1111 return {