You've already forked pigallery2
mirror of
https://github.com/bpatrik/pigallery2.git
synced 2025-11-23 22:24:44 +02:00
Fixing benchmark (Adding new search cases after advanced search is ready)
This commit is contained in:
@@ -19,8 +19,17 @@ import {PersonManager} from '../src/backend/model/database/sql/PersonManager';
|
|||||||
import {GalleryRouter} from '../src/backend/routes/GalleryRouter';
|
import {GalleryRouter} from '../src/backend/routes/GalleryRouter';
|
||||||
import {Express} from 'express';
|
import {Express} from 'express';
|
||||||
import {PersonRouter} from '../src/backend/routes/PersonRouter';
|
import {PersonRouter} from '../src/backend/routes/PersonRouter';
|
||||||
import {QueryParams} from '../src/common/QueryParams';
|
import {
|
||||||
import {SearchQueryTypes, TextSearch} from '../src/common/entities/SearchQueryDTO';
|
ANDSearchQuery,
|
||||||
|
ORSearchQuery,
|
||||||
|
SearchQueryDTO,
|
||||||
|
SearchQueryTypes,
|
||||||
|
SomeOfSearchQuery,
|
||||||
|
TextSearch,
|
||||||
|
TextSearchQueryMatchTypes,
|
||||||
|
TextSearchQueryTypes
|
||||||
|
} from '../src/common/entities/SearchQueryDTO';
|
||||||
|
import {QueryKeywords, SearchQueryParser} from '../src/common/SearchQueryParser';
|
||||||
|
|
||||||
|
|
||||||
export interface BenchmarkResult {
|
export interface BenchmarkResult {
|
||||||
@@ -124,18 +133,107 @@ export class BenchmarkRunner {
|
|||||||
return await bm.run(this.RUNS);
|
return await bm.run(this.RUNS);
|
||||||
}
|
}
|
||||||
|
|
||||||
async bmAllSearch(text: string): Promise<{ result: BenchmarkResult, searchType: SearchQueryTypes }[]> {
|
async bmAllSearch(): Promise<{ result: BenchmarkResult, searchQuery: SearchQueryDTO }[]> {
|
||||||
await this.setupDB();
|
await this.setupDB();
|
||||||
const types = Utils.enumToArray(SearchQueryTypes).map((a): number => a.key).concat([null]);
|
|
||||||
const results: { result: BenchmarkResult, searchType: SearchQueryTypes }[] = [];
|
|
||||||
|
|
||||||
for (const type of types) {
|
const queryKeywords: QueryKeywords = {
|
||||||
|
NSomeOf: '-of',
|
||||||
|
and: 'and',
|
||||||
|
caption: 'caption',
|
||||||
|
directory: 'directory',
|
||||||
|
file_name: 'file-name',
|
||||||
|
from: 'from',
|
||||||
|
keyword: 'keyword',
|
||||||
|
landscape: 'landscape',
|
||||||
|
maxRating: 'max-rating',
|
||||||
|
maxResolution: 'max-resolution',
|
||||||
|
minRating: 'min-rating',
|
||||||
|
minResolution: 'min-resolution',
|
||||||
|
or: 'or',
|
||||||
|
orientation: 'orientation',
|
||||||
|
person: 'person',
|
||||||
|
portrait: 'portrait',
|
||||||
|
position: 'position',
|
||||||
|
someOf: 'some-of',
|
||||||
|
to: 'to',
|
||||||
|
kmFrom: 'km-from'
|
||||||
|
};
|
||||||
|
const queryParser = new SearchQueryParser(queryKeywords);
|
||||||
|
const names = (await ObjectManagers.getInstance().PersonManager.getAll()).sort((a, b) => b.count - a.count);
|
||||||
|
const queries: { query: SearchQueryDTO, description: string }[] = TextSearchQueryTypes.map(t => {
|
||||||
|
const q = {
|
||||||
|
type: t, text: 'a'
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
query: q, description: queryParser.stringify(q)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
// searching for everything
|
||||||
|
queries.push({
|
||||||
|
query: {
|
||||||
|
type: SearchQueryTypes.any_text, text: '.'
|
||||||
|
} as TextSearch, description: queryParser.stringify({
|
||||||
|
type: SearchQueryTypes.any_text, text: '.'
|
||||||
|
} as TextSearch)
|
||||||
|
});
|
||||||
|
if (names.length > 0) {
|
||||||
|
queries.push({
|
||||||
|
query: {
|
||||||
|
type: SearchQueryTypes.person, text: names[0].name,
|
||||||
|
matchType: TextSearchQueryMatchTypes.exact_match
|
||||||
|
} as TextSearch, description: '<Most common name>'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (names.length > 1) {
|
||||||
|
queries.push({
|
||||||
|
query: {
|
||||||
|
type: SearchQueryTypes.AND, list: [
|
||||||
|
{
|
||||||
|
type: SearchQueryTypes.person, text: names[0].name,
|
||||||
|
matchType: TextSearchQueryMatchTypes.exact_match
|
||||||
|
} as TextSearch,
|
||||||
|
{
|
||||||
|
type: SearchQueryTypes.person, text: names[1].name,
|
||||||
|
matchType: TextSearchQueryMatchTypes.exact_match
|
||||||
|
} as TextSearch
|
||||||
|
]
|
||||||
|
} as ANDSearchQuery, description: '<Most AND second common names>'
|
||||||
|
});
|
||||||
|
queries.push({
|
||||||
|
query: {
|
||||||
|
type: SearchQueryTypes.OR, list: [
|
||||||
|
{
|
||||||
|
type: SearchQueryTypes.person, text: names[0].name,
|
||||||
|
matchType: TextSearchQueryMatchTypes.exact_match
|
||||||
|
} as TextSearch,
|
||||||
|
{
|
||||||
|
type: SearchQueryTypes.person, text: names[1].name,
|
||||||
|
matchType: TextSearchQueryMatchTypes.exact_match
|
||||||
|
} as TextSearch
|
||||||
|
]
|
||||||
|
} as ORSearchQuery, description: '<Most OR second common names>'
|
||||||
|
});
|
||||||
|
queries.push({
|
||||||
|
query: {
|
||||||
|
type: SearchQueryTypes.SOME_OF,
|
||||||
|
min: 2,
|
||||||
|
list: names.map(n => ({
|
||||||
|
type: SearchQueryTypes.person, text: n.name,
|
||||||
|
matchType: TextSearchQueryMatchTypes.exact_match
|
||||||
|
} as TextSearch))
|
||||||
|
} as SomeOfSearchQuery, description: '<Contain at least 2 out of all names>'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const results: { result: BenchmarkResult, searchQuery: SearchQueryDTO }[] = [];
|
||||||
|
|
||||||
|
for (const entry of queries) {
|
||||||
const req = Utils.clone(this.requestTemplate);
|
const req = Utils.clone(this.requestTemplate);
|
||||||
req.query[QueryParams.gallery.search.query] = ({type, text} as TextSearch);
|
req.params.searchQueryDTO = JSON.stringify(entry.query);
|
||||||
const bm = new Benchmark('Searching for `' + text + '` as `' + (type ? SearchQueryTypes[type] : 'any') + '`', req);
|
|
||||||
|
const bm = new Benchmark('Searching for `' + entry.description + '`', req);
|
||||||
BMGalleryRouter.addSearch(bm.BmExpressApp);
|
BMGalleryRouter.addSearch(bm.BmExpressApp);
|
||||||
|
|
||||||
results.push({result: await bm.run(this.RUNS), searchType: type});
|
results.push({result: await bm.run(this.RUNS), searchQuery: entry.query});
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ const run = async () => {
|
|||||||
printResult(await bm.bmSaveDirectory());
|
printResult(await bm.bmSaveDirectory());
|
||||||
printResult(await bm.bmListDirectory());
|
printResult(await bm.bmListDirectory());
|
||||||
printResult(await bm.bmListPersons());
|
printResult(await bm.bmListPersons());
|
||||||
(await bm.bmAllSearch('a')).forEach(res => printResult(res.result));
|
(await bm.bmAllSearch()).forEach(res => printResult(res.result));
|
||||||
printResult(await bm.bmAutocomplete('a'));
|
printResult(await bm.bmAutocomplete('a'));
|
||||||
printLine('*Measurements run ' + RUNS + ' times and an average was calculated.');
|
printLine('*Measurements run ' + RUNS + ' times and an average was calculated.');
|
||||||
console.log(resultsText);
|
console.log(resultsText);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {ContentWrapper} from '../../common/entities/ConentWrapper';
|
|||||||
import {PhotoDTO} from '../../common/entities/PhotoDTO';
|
import {PhotoDTO} from '../../common/entities/PhotoDTO';
|
||||||
import {ProjectPath} from '../ProjectPath';
|
import {ProjectPath} from '../ProjectPath';
|
||||||
import {Config} from '../../common/config/private/Config';
|
import {Config} from '../../common/config/private/Config';
|
||||||
import {UserDTO, UserDTOUtils} from '../../common/entities/UserDTO';
|
import {UserDTOUtils} from '../../common/entities/UserDTO';
|
||||||
import {MediaDTO, MediaDTOUtils} from '../../common/entities/MediaDTO';
|
import {MediaDTO, MediaDTOUtils} from '../../common/entities/MediaDTO';
|
||||||
import {VideoDTO} from '../../common/entities/VideoDTO';
|
import {VideoDTO} from '../../common/entities/VideoDTO';
|
||||||
import {Utils} from '../../common/Utils';
|
import {Utils} from '../../common/Utils';
|
||||||
@@ -79,11 +79,11 @@ export class GalleryMWs {
|
|||||||
store: true, // disable compression
|
store: true, // disable compression
|
||||||
});
|
});
|
||||||
|
|
||||||
res.on('close', function() {
|
res.on('close', () => {
|
||||||
console.log('zip ' + archive.pointer() + ' bytes');
|
console.log('zip ' + archive.pointer() + ' bytes');
|
||||||
});
|
});
|
||||||
|
|
||||||
archive.on('error', function(err: any) {
|
archive.on('error', (err: any) => {
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -92,12 +92,12 @@ export class GalleryMWs {
|
|||||||
// append photos in absoluteDirectoryName
|
// append photos in absoluteDirectoryName
|
||||||
// using case-insensitive glob of extensions
|
// using case-insensitive glob of extensions
|
||||||
for (const ext of SupportedFormats.WithDots.Photos) {
|
for (const ext of SupportedFormats.WithDots.Photos) {
|
||||||
archive.glob(`*${ext}`, {cwd:absoluteDirectoryName, nocase:true});
|
archive.glob(`*${ext}`, {cwd: absoluteDirectoryName, nocase: true});
|
||||||
}
|
}
|
||||||
// append videos in absoluteDirectoryName
|
// append videos in absoluteDirectoryName
|
||||||
// using case-insensitive glob of extensions
|
// using case-insensitive glob of extensions
|
||||||
for (const ext of SupportedFormats.WithDots.Videos) {
|
for (const ext of SupportedFormats.WithDots.Videos) {
|
||||||
archive.glob(`*${ext}`, {cwd:absoluteDirectoryName, nocase:true});
|
archive.glob(`*${ext}`, {cwd: absoluteDirectoryName, nocase: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
await archive.finalize();
|
await archive.finalize();
|
||||||
|
|||||||
@@ -19,33 +19,33 @@ import {
|
|||||||
} from '../../../src/common/entities/SearchQueryDTO';
|
} from '../../../src/common/entities/SearchQueryDTO';
|
||||||
import {QueryKeywords, SearchQueryParser} from '../../../src/common/SearchQueryParser';
|
import {QueryKeywords, SearchQueryParser} from '../../../src/common/SearchQueryParser';
|
||||||
|
|
||||||
|
const queryKeywords: QueryKeywords = {
|
||||||
|
NSomeOf: '-of',
|
||||||
|
and: 'and',
|
||||||
|
caption: 'caption',
|
||||||
|
directory: 'directory',
|
||||||
|
file_name: 'file-name',
|
||||||
|
from: 'from',
|
||||||
|
keyword: 'keyword',
|
||||||
|
landscape: 'landscape',
|
||||||
|
maxRating: 'max-rating',
|
||||||
|
maxResolution: 'max-resolution',
|
||||||
|
minRating: 'min-rating',
|
||||||
|
minResolution: 'min-resolution',
|
||||||
|
or: 'or',
|
||||||
|
orientation: 'orientation',
|
||||||
|
person: 'person',
|
||||||
|
portrait: 'portrait',
|
||||||
|
position: 'position',
|
||||||
|
someOf: 'some-of',
|
||||||
|
to: 'to',
|
||||||
|
kmFrom: 'km-from'
|
||||||
|
};
|
||||||
|
|
||||||
describe('SearchQueryParser', () => {
|
describe('SearchQueryParser', () => {
|
||||||
|
|
||||||
const keywords: QueryKeywords = {
|
|
||||||
NSomeOf: '-of',
|
|
||||||
and: 'and',
|
|
||||||
caption: 'caption',
|
|
||||||
directory: 'directory',
|
|
||||||
file_name: 'file-name',
|
|
||||||
from: 'from',
|
|
||||||
keyword: 'keyword',
|
|
||||||
landscape: 'landscape',
|
|
||||||
maxRating: 'max-rating',
|
|
||||||
maxResolution: 'max-resolution',
|
|
||||||
minRating: 'min-rating',
|
|
||||||
minResolution: 'min-resolution',
|
|
||||||
or: 'or',
|
|
||||||
orientation: 'orientation',
|
|
||||||
person: 'person',
|
|
||||||
portrait: 'portrait',
|
|
||||||
position: 'position',
|
|
||||||
someOf: 'some-of',
|
|
||||||
to: 'to',
|
|
||||||
kmFrom: 'km-from'
|
|
||||||
};
|
|
||||||
|
|
||||||
const check = (query: SearchQueryDTO) => {
|
const check = (query: SearchQueryDTO) => {
|
||||||
const parser = new SearchQueryParser(keywords);
|
const parser = new SearchQueryParser(queryKeywords);
|
||||||
expect(parser.parse(parser.stringify(query))).to.deep.equals(query, parser.stringify(query));
|
expect(parser.parse(parser.stringify(query))).to.deep.equals(query, parser.stringify(query));
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -72,14 +72,14 @@ describe('SearchQueryParser', () => {
|
|||||||
check({type: SearchQueryTypes.to_date, value: (new Date(2020, 1, 20)).getTime()} as ToDateSearch);
|
check({type: SearchQueryTypes.to_date, value: (new Date(2020, 1, 20)).getTime()} as ToDateSearch);
|
||||||
check({type: SearchQueryTypes.to_date, value: (new Date(2020, 1, 1)).getTime()} as ToDateSearch);
|
check({type: SearchQueryTypes.to_date, value: (new Date(2020, 1, 1)).getTime()} as ToDateSearch);
|
||||||
|
|
||||||
const parser = new SearchQueryParser(keywords);
|
const parser = new SearchQueryParser(queryKeywords);
|
||||||
// test if date gets simplified on 1st of Jan.
|
// test if date gets simplified on 1st of Jan.
|
||||||
let query: RangeSearch = {type: SearchQueryTypes.to_date, value: (new Date(2020, 0, 1)).getTime()} as ToDateSearch;
|
let query: RangeSearch = {type: SearchQueryTypes.to_date, value: (new Date(2020, 0, 1)).getTime()} as ToDateSearch;
|
||||||
expect(parser.parse(keywords.to + ':' + (new Date(query.value)).getFullYear()))
|
expect(parser.parse(queryKeywords.to + ':' + (new Date(query.value)).getFullYear()))
|
||||||
.to.deep.equals(query, parser.stringify(query));
|
.to.deep.equals(query, parser.stringify(query));
|
||||||
|
|
||||||
query = ({type: SearchQueryTypes.from_date, value: (new Date(2020, 0, 1)).getTime()} as FromDateSearch);
|
query = ({type: SearchQueryTypes.from_date, value: (new Date(2020, 0, 1)).getTime()} as FromDateSearch);
|
||||||
expect(parser.parse(keywords.from + ':' + (new Date(query.value)).getFullYear()))
|
expect(parser.parse(queryKeywords.from + ':' + (new Date(query.value)).getFullYear()))
|
||||||
.to.deep.equals(query, parser.stringify(query));
|
.to.deep.equals(query, parser.stringify(query));
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user