Add ability to only filter in the search endpoint
This commit is contained in:
parent
cddf450353
commit
d411245096
4 changed files with 90 additions and 6 deletions
|
@ -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'),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { NSFWQuery } from './nsfw-query.model'
|
||||
|
||||
export interface VideosSearchQuery {
|
||||
search: string
|
||||
search?: string
|
||||
|
||||
start?: number
|
||||
count?: number
|
||||
|
|
Loading…
Reference in a new issue