X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Fmodels%2Fvideo%2Ftag.ts;h=7900e070dd8a0dfa4205859b20fb081fc1dc49ed;hb=69c1f3c25622500e0956127a2493bba54fce97f8;hp=2992da56db8f92cc6eed4ab7cb50cfd96d48bc09;hpb=e6d4b0ff2404dcf0b3a755c3fcc415ffeb6e754d;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/models/video/tag.ts b/server/models/video/tag.ts index 2992da56d..7900e070d 100644 --- a/server/models/video/tag.ts +++ b/server/models/video/tag.ts @@ -1,73 +1,86 @@ -import * as Sequelize from 'sequelize' -import * as Promise from 'bluebird' +import { col, fn, QueryTypes, Transaction } from 'sequelize' +import { AllowNull, BelongsToMany, Column, CreatedAt, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' +import { MTag } from '@server/types/models' +import { AttributesOnly } from '@shared/typescript-utils' +import { VideoPrivacy, VideoState } from '../../../shared/models/videos' +import { isVideoTagValid } from '../../helpers/custom-validators/videos' +import { throwIfNotValid } from '../utils' +import { VideoModel } from './video' +import { VideoTagModel } from './video-tag' -import { addMethodsToModel } from '../utils' -import { - TagInstance, - TagAttributes, - - TagMethods -} from './tag-interface' - -let Tag: Sequelize.Model -let findOrCreateTags: TagMethods.FindOrCreateTags - -export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) { - Tag = sequelize.define('Tag', +@Table({ + tableName: 'tag', + timestamps: false, + indexes: [ { - name: { - type: DataTypes.STRING, - allowNull: false - } + fields: [ 'name' ], + unique: true }, { - timestamps: false, - indexes: [ - { - fields: [ 'name' ], - unique: true - } - ] + name: 'tag_lower_name', + fields: [ fn('lower', col('name')) ] } - ) - - const classMethods = [ - associate, - - findOrCreateTags ] - addMethodsToModel(Tag, classMethods) +}) +export class TagModel extends Model>> { - return Tag -} + @AllowNull(false) + @Is('VideoTag', value => throwIfNotValid(value, isVideoTagValid, 'tag')) + @Column + name: string + + @CreatedAt + createdAt: Date -// --------------------------------------------------------------------------- + @UpdatedAt + updatedAt: Date -function associate (models) { - Tag.belongsToMany(models.Video, { + @BelongsToMany(() => VideoModel, { foreignKey: 'tagId', - through: models.VideoTag, - onDelete: 'cascade' + through: () => VideoTagModel, + onDelete: 'CASCADE' }) -} + Videos: VideoModel[] + + static findOrCreateTags (tags: string[], transaction: Transaction): Promise { + if (tags === null) return Promise.resolve([]) -findOrCreateTags = function (tags: string[], transaction: Sequelize.Transaction) { - const tasks: Promise[] = [] - tags.forEach(tag => { - const query: Sequelize.FindOrInitializeOptions = { - where: { - name: tag - }, - defaults: { - name: tag + const tasks: Promise[] = [] + tags.forEach(tag => { + const query = { + where: { + name: tag + }, + defaults: { + name: tag + }, + transaction } - } - if (transaction) query.transaction = transaction + const promise = TagModel.findOrCreate(query) + .then(([ tagInstance ]) => tagInstance) + tasks.push(promise) + }) - const promise = Tag.findOrCreate(query).then(([ tagInstance ]) => tagInstance) - tasks.push(promise) - }) + return Promise.all(tasks) + } + + // threshold corresponds to how many video the field should have to be returned + static getRandomSamples (threshold: number, count: number): Promise { + const query = 'SELECT tag.name FROM tag ' + + 'INNER JOIN "videoTag" ON "videoTag"."tagId" = tag.id ' + + 'INNER JOIN video ON video.id = "videoTag"."videoId" ' + + 'WHERE video.privacy = $videoPrivacy AND video.state = $videoState ' + + 'GROUP BY tag.name HAVING COUNT(tag.name) >= $threshold ' + + 'ORDER BY random() ' + + 'LIMIT $count' + + const options = { + bind: { threshold, count, videoPrivacy: VideoPrivacy.PUBLIC, videoState: VideoState.PUBLISHED }, + type: QueryTypes.SELECT as QueryTypes.SELECT + } - return Promise.all(tasks) + return TagModel.sequelize.query<{ name: string }>(query, options) + .then(data => data.map(d => d.name)) + } }