1
0
Fork 0

Add ability to only filter in the search endpoint

This commit is contained in:
Chocobozzz 2018-07-24 11:09:00 +02:00
parent cddf450353
commit d411245096
4 changed files with 90 additions and 6 deletions

View File

@ -6,7 +6,7 @@ import { isNumberArray, isStringArray, isNSFWQueryValid } from '../../helpers/cu
import { isBooleanValid, isDateValid, toArray } from '../../helpers/custom-validators/misc' import { isBooleanValid, isDateValid, toArray } from '../../helpers/custom-validators/misc'
const searchValidator = [ const searchValidator = [
query('search').not().isEmpty().withMessage('Should have a valid search'), query('search').optional().not().isEmpty().withMessage('Should have a valid search'),
query('startDate').optional().custom(isDateValid).withMessage('Should have a valid start date'), query('startDate').optional().custom(isDateValid).withMessage('Should have a valid start date'),
query('endDate').optional().custom(isDateValid).withMessage('Should have a valid end date'), query('endDate').optional().custom(isDateValid).withMessage('Should have a valid end date'),

View File

@ -93,7 +93,6 @@ import { VideoShareModel } from './video-share'
import { VideoTagModel } from './video-tag' import { VideoTagModel } from './video-tag'
import { ScheduleVideoUpdateModel } from './schedule-video-update' import { ScheduleVideoUpdateModel } from './schedule-video-update'
import { VideoCaptionModel } from './video-caption' import { VideoCaptionModel } from './video-caption'
import { VideosSearchQuery } from '../../../shared/models/search'
// FIXME: Define indexes here because there is an issue with TS and Sequelize.literal when called directly in the annotation // FIXME: Define indexes here because there is an issue with TS and Sequelize.literal when called directly in the annotation
const indexes: Sequelize.DefineIndexesOptions[] = [ const indexes: Sequelize.DefineIndexesOptions[] = [
@ -848,7 +847,7 @@ export class VideoModel extends Model<VideoModel> {
} }
static async searchAndPopulateAccountAndServer (options: { static async searchAndPopulateAccountAndServer (options: {
search: string search?: string
start?: number start?: number
count?: number count?: number
sort?: string sort?: string
@ -883,11 +882,41 @@ export class VideoModel extends Model<VideoModel> {
whereAnd.push({ duration: durationRange }) whereAnd.push({ duration: durationRange })
} }
whereAnd.push(createSearchTrigramQuery('VideoModel.name', options.search)) const attributesInclude = []
if (options.search) {
whereAnd.push(
{
[ Sequelize.Op.or ]: [
createSearchTrigramQuery('VideoModel.name', options.search),
{
id: {
[ Sequelize.Op.in ]: Sequelize.literal(
'(' +
'SELECT "video"."id" FROM "video" LEFT JOIN "videoTag" ON "videoTag"."videoId" = "video"."id" ' +
'INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' +
'WHERE "tag"."name" = ' + VideoModel.sequelize.escape(options.search) +
')'
)
}
}
]
}
)
attributesInclude.push(createSimilarityAttribute('VideoModel.name', options.search))
}
// Cannot search on similarity if we don't have a search
if (!options.search) {
attributesInclude.push(
Sequelize.literal('0 as similarity')
)
}
const query: IFindOptions<VideoModel> = { const query: IFindOptions<VideoModel> = {
attributes: { attributes: {
include: [ createSimilarityAttribute('VideoModel.name', options.search) ] include: attributesInclude
}, },
offset: options.start, offset: options.start,
limit: options.count, limit: options.count,

View File

@ -103,6 +103,15 @@ describe('Test a videos search', function () {
await uploadVideo(server.url, server.accessToken, immutableAssign(attributes1, { tags: [ 'cccc', 'dddd' ] })) await uploadVideo(server.url, server.accessToken, immutableAssign(attributes1, { tags: [ 'cccc', 'dddd' ] }))
await uploadVideo(server.url, server.accessToken, immutableAssign(attributes1, { tags: [ 'eeee', 'ffff' ] })) await uploadVideo(server.url, server.accessToken, immutableAssign(attributes1, { tags: [ 'eeee', 'ffff' ] }))
} }
{
const attributes1 = {
name: 'aaaa 2',
category: 1
}
await uploadVideo(server.url, server.accessToken, attributes1)
await uploadVideo(server.url, server.accessToken, immutableAssign(attributes1, { category: 2 }))
}
}) })
it('Should make a simple search and not have results', async function () { it('Should make a simple search and not have results', async function () {
@ -125,6 +134,52 @@ describe('Test a videos search', function () {
expect(videos[1].name).to.equal('3333 4444 5555') expect(videos[1].name).to.equal('3333 4444 5555')
}) })
it('Should make a search on tags too, and have results', async function () {
const query = {
search: 'aaaa',
categoryOneOf: [ 1 ]
}
const res = await advancedVideosSearch(server.url, query)
expect(res.body.total).to.equal(2)
const videos = res.body.data
expect(videos).to.have.lengthOf(2)
// bestmatch
expect(videos[0].name).to.equal('aaaa 2')
expect(videos[1].name).to.equal('9999')
})
it('Should filter on tags without a search', async function () {
const query = {
tagsAllOf: [ 'bbbb' ]
}
const res = await advancedVideosSearch(server.url, query)
expect(res.body.total).to.equal(2)
const videos = res.body.data
expect(videos).to.have.lengthOf(2)
expect(videos[0].name).to.equal('9999')
expect(videos[1].name).to.equal('9999')
})
it('Should filter on category without a search', async function () {
const query = {
categoryOneOf: [ 3 ]
}
const res = await advancedVideosSearch(server.url, query)
expect(res.body.total).to.equal(1)
const videos = res.body.data
expect(videos).to.have.lengthOf(1)
expect(videos[0].name).to.equal('6666 7777 8888')
})
it('Should search by tags (one of)', async function () { it('Should search by tags (one of)', async function () {
const query = { const query = {
search: '9999', search: '9999',

View File

@ -1,7 +1,7 @@
import { NSFWQuery } from './nsfw-query.model' import { NSFWQuery } from './nsfw-query.model'
export interface VideosSearchQuery { export interface VideosSearchQuery {
search: string search?: string
start?: number start?: number
count?: number count?: number