From 7920c273a204e2469416a30b752b12ccd3160102 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Sat, 24 Dec 2016 16:59:17 +0100 Subject: Move tags in another table --- server/models/pod.js | 3 +- server/models/request.js | 6 ++- server/models/tag.js | 30 +++++++++++++++ server/models/video.js | 97 ++++++++++++++++++++++++++++------------------- server/models/videoTag.js | 9 +++++ 5 files changed, 101 insertions(+), 44 deletions(-) create mode 100644 server/models/tag.js create mode 100644 server/models/videoTag.js (limited to 'server/models') diff --git a/server/models/pod.js b/server/models/pod.js index 2c1f56203..fff6970a7 100644 --- a/server/models/pod.js +++ b/server/models/pod.js @@ -19,7 +19,6 @@ module.exports = function (sequelize, DataTypes) { type: DataTypes.INTEGER, defaultValue: constants.FRIEND_SCORE.BASE } - // Check createdAt }, { classMethods: { @@ -68,7 +67,7 @@ function associate (models) { this.belongsToMany(models.Request, { foreignKey: 'podId', through: models.RequestToPod, - onDelete: 'CASCADE' + onDelete: 'cascade' }) } diff --git a/server/models/request.js b/server/models/request.js index 882f747b7..70aa32610 100644 --- a/server/models/request.js +++ b/server/models/request.js @@ -79,9 +79,11 @@ function deactivate () { timer = null } -function flush () { +function flush (callback) { removeAll.call(this, function (err) { if (err) logger.error('Cannot flush the requests.', { error: err }) + + return callback(err) }) } @@ -298,7 +300,7 @@ function listWithLimitAndRandom (limit, callback) { function removeAll (callback) { // Delete all requests - this.destroy({ truncate: true }).asCallback(callback) + this.truncate({ cascade: true }).asCallback(callback) } function removeWithEmptyTo (callback) { diff --git a/server/models/tag.js b/server/models/tag.js new file mode 100644 index 000000000..874e88842 --- /dev/null +++ b/server/models/tag.js @@ -0,0 +1,30 @@ +'use strict' + +// --------------------------------------------------------------------------- + +module.exports = function (sequelize, DataTypes) { + const Tag = sequelize.define('Tag', + { + name: { + type: DataTypes.STRING + } + }, + { + classMethods: { + associate + } + } + ) + + return Tag +} + +// --------------------------------------------------------------------------- + +function associate (models) { + this.belongsToMany(models.Video, { + foreignKey: 'tagId', + through: models.VideoTag, + onDelete: 'cascade' + }) +} diff --git a/server/models/video.js b/server/models/video.js index 8ef07c9e6..0023a24e1 100644 --- a/server/models/video.js +++ b/server/models/video.js @@ -4,6 +4,7 @@ const createTorrent = require('create-torrent') const ffmpeg = require('fluent-ffmpeg') const fs = require('fs') const magnetUtil = require('magnet-uri') +const map = require('lodash/map') const parallel = require('async/parallel') const parseTorrent = require('parse-torrent') const pathUtils = require('path') @@ -41,9 +42,6 @@ module.exports = function (sequelize, DataTypes) { }, duration: { type: DataTypes.INTEGER - }, - tags: { - type: DataTypes.ARRAY(DataTypes.STRING) } }, { @@ -54,12 +52,12 @@ module.exports = function (sequelize, DataTypes) { getDurationFromFile, listForApi, listByHostAndRemoteId, - listOwnedAndPopulateAuthor, + listOwnedAndPopulateAuthorAndTags, listOwnedByAuthor, load, loadAndPopulateAuthor, - loadAndPopulateAuthorAndPod, - searchAndPopulateAuthorAndPod + loadAndPopulateAuthorAndPodAndTags, + searchAndPopulateAuthorAndPodAndTags }, instanceMethods: { generateMagnetUri, @@ -170,6 +168,12 @@ function associate (models) { }, onDelete: 'cascade' }) + + this.belongsToMany(models.Tag, { + foreignKey: 'videoId', + through: models.VideoTag, + onDelete: 'cascade' + }) } function generateMagnetUri () { @@ -248,7 +252,7 @@ function toFormatedJSON () { magnetUri: this.generateMagnetUri(), author: this.Author.name, duration: this.duration, - tags: this.tags, + tags: map(this.Tags, 'name'), thumbnailPath: constants.STATIC_PATHS.THUMBNAILS + '/' + this.getThumbnailName(), createdAt: this.createdAt } @@ -275,7 +279,7 @@ function toRemoteJSON (callback) { author: self.Author.name, duration: self.duration, thumbnailBase64: new Buffer(thumbnailData).toString('base64'), - tags: self.tags, + tags: map(self.Tags, 'name'), createdAt: self.createdAt, extname: self.extname } @@ -310,12 +314,15 @@ function listForApi (start, count, sort, callback) { const query = { offset: start, limit: count, + distinct: true, // For the count, a video can have many tags order: [ modelUtils.getSort(sort) ], include: [ { model: this.sequelize.models.Author, - include: [ this.sequelize.models.Pod ] - } + include: [ { model: this.sequelize.models.Pod, required: false } ] + }, + + this.sequelize.models.Tag ] } @@ -337,6 +344,7 @@ function listByHostAndRemoteId (fromHost, remoteId, callback) { include: [ { model: this.sequelize.models.Pod, + required: true, where: { host: fromHost } @@ -349,13 +357,13 @@ function listByHostAndRemoteId (fromHost, remoteId, callback) { return this.findAll(query).asCallback(callback) } -function listOwnedAndPopulateAuthor (callback) { +function listOwnedAndPopulateAuthorAndTags (callback) { // If remoteId is null this is *our* video const query = { where: { remoteId: null }, - include: [ this.sequelize.models.Author ] + include: [ this.sequelize.models.Author, this.sequelize.models.Tag ] } return this.findAll(query).asCallback(callback) @@ -391,23 +399,26 @@ function loadAndPopulateAuthor (id, callback) { return this.findById(id, options).asCallback(callback) } -function loadAndPopulateAuthorAndPod (id, callback) { +function loadAndPopulateAuthorAndPodAndTags (id, callback) { const options = { include: [ { model: this.sequelize.models.Author, - include: [ this.sequelize.models.Pod ] - } + include: [ { model: this.sequelize.models.Pod, required: false } ] + }, + this.sequelize.models.Tag ] } return this.findById(id, options).asCallback(callback) } -function searchAndPopulateAuthorAndPod (value, field, start, count, sort, callback) { +function searchAndPopulateAuthorAndPodAndTags (value, field, start, count, sort, callback) { const podInclude = { - model: this.sequelize.models.Pod + model: this.sequelize.models.Pod, + required: false } + const authorInclude = { model: this.sequelize.models.Author, include: [ @@ -415,55 +426,61 @@ function searchAndPopulateAuthorAndPod (value, field, start, count, sort, callba ] } + const tagInclude = { + model: this.sequelize.models.Tag + } + const query = { where: {}, - include: [ - authorInclude - ], offset: start, limit: count, + distinct: true, // For the count, a video can have many tags order: [ modelUtils.getSort(sort) ] } - // TODO: include our pod for podHost searches (we are not stored in the database) // Make an exact search with the magnet if (field === 'magnetUri') { const infoHash = magnetUtil.decode(value).infoHash query.where.infoHash = infoHash } else if (field === 'tags') { - query.where[field] = value - } else if (field === 'host') { - const whereQuery = { - '$Author.Pod.host$': { - $like: '%' + value + '%' + const escapedValue = this.sequelize.escape('%' + value + '%') + query.where = { + id: { + $in: this.sequelize.literal( + '(SELECT "VideoTags"."videoId" FROM "Tags" INNER JOIN "VideoTags" ON "Tags"."id" = "VideoTags"."tagId" WHERE name LIKE ' + escapedValue + ')' + ) } } - - // Include our pod? (not stored in the database) - if (constants.CONFIG.WEBSERVER.HOST.indexOf(value) !== -1) { - query.where = { - $or: [ - whereQuery, - { - remoteId: null - } - ] + } else if (field === 'host') { + // FIXME: Include our pod? (not stored in the database) + podInclude.where = { + host: { + $like: '%' + value + '%' } - } else { - query.where = whereQuery } + podInclude.required = true } else if (field === 'author') { - query.where = { - '$Author.name$': { + authorInclude.where = { + name: { $like: '%' + value + '%' } } + + // authorInclude.or = true } else { query.where[field] = { $like: '%' + value + '%' } } + query.include = [ + authorInclude, tagInclude + ] + + if (tagInclude.where) { + // query.include.push([ this.sequelize.models.Tag ]) + } + return this.findAndCountAll(query).asCallback(function (err, result) { if (err) return callback(err) diff --git a/server/models/videoTag.js b/server/models/videoTag.js new file mode 100644 index 000000000..0f2b20838 --- /dev/null +++ b/server/models/videoTag.js @@ -0,0 +1,9 @@ +'use strict' + +// --------------------------------------------------------------------------- + +module.exports = function (sequelize, DataTypes) { + const VideoTag = sequelize.define('VideoTag', {}, {}) + + return VideoTag +} -- cgit v1.2.3