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'
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('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 { ScheduleVideoUpdateModel } from './schedule-video-update'
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
const indexes: Sequelize.DefineIndexesOptions[] = [
@ -848,7 +847,7 @@ export class VideoModel extends Model<VideoModel> {
}
static async searchAndPopulateAccountAndServer (options: {
search: string
search?: string
start?: number
count?: number
sort?: string
@ -883,11 +882,41 @@ export class VideoModel extends Model<VideoModel> {
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> = {
attributes: {
include: [ createSimilarityAttribute('VideoModel.name', options.search) ]
include: attributesInclude
},
offset: options.start,
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: [ '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 () {
@ -125,6 +134,52 @@ describe('Test a videos search', function () {
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 () {
const query = {
search: '9999',

View file

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