1
0
mirror of https://github.com/xuthus83/pigallery2.git synced 2024-11-03 21:04:03 +08:00

Fixing parsing errors.

This commit is contained in:
Patrik J. Braun 2021-03-14 10:56:59 +01:00
parent 47703b6b84
commit 41292ec4b4
4 changed files with 102 additions and 41 deletions

View File

@ -274,9 +274,7 @@ export class SearchManager implements ISearchManager {
if (typeof (<FromDateSearch>query).value === 'undefined') {
throw new Error('Invalid search query: Date Query should contain from value');
}
const whereFN = (<TextSearch>query).negate ? 'orWhere' : 'andWhere';
const relation = (<TextSearch>query).negate ? '<' : '>=';
const relationRev = (<TextSearch>query).negate ? '>' : '<=';
const textParam: any = {};
textParam['from' + paramCounter.value] = (<FromDateSearch>query).value;

View File

@ -2,7 +2,7 @@ import {GPSMetadata} from './PhotoDTO';
import {Utils} from '../Utils';
export enum SearchQueryTypes {
AND = 1, OR, SOME_OF,
AND = 1, OR, SOME_OF, UNKNOWN_RELATION = 99999,
// non-text metadata
// |- range types
@ -120,17 +120,22 @@ export namespace SearchQueryDTO {
}
};
export const parse = (str: string): SearchQueryDTO => {
console.log(str);
export const parse = (str: string, implicitOR = true): SearchQueryDTO => {
console.log('parsing: ' + str);
str = str.replace(/\s\s+/g, ' ') // remove double spaces
.replace(/:\s+/g, ':').replace(/\)(?=\S)/g, ') ').trim();
if (str.charAt(0) === '(' && str.charAt(str.length - 1) === ')') {
str = str.slice(1, str.length - 1);
}
const fistNonBRSpace = () => {
const fistSpace = (start = 0) => {
const bracketIn = [];
for (let i = 0; i < str.length; ++i) {
let quotationMark = false;
for (let i = start; i < str.length; ++i) {
if (str.charAt(i) === '"') {
quotationMark = !quotationMark;
continue;
}
if (str.charAt(i) === '(') {
bracketIn.push(i);
continue;
@ -140,7 +145,9 @@ export namespace SearchQueryDTO {
continue;
}
if (bracketIn.length === 0 && str.charAt(i) === ' ') {
if (quotationMark === false &&
bracketIn.length === 0 &&
str.charAt(i) === ' ') {
return i;
}
}
@ -148,34 +155,41 @@ export namespace SearchQueryDTO {
};
// tokenize
const tokenEnd = fistNonBRSpace();
const tokenEnd = fistSpace();
if (tokenEnd !== str.length - 1) {
if (str.startsWith(' and', tokenEnd)) {
return <ANDSearchQuery>{
type: SearchQueryTypes.AND,
list: [SearchQueryDTO.parse(str.slice(0, tokenEnd)), // trim brackets
SearchQueryDTO.parse(str.slice(tokenEnd + 4))]
list: [SearchQueryDTO.parse(str.slice(0, tokenEnd), implicitOR), // trim brackets
SearchQueryDTO.parse(str.slice(tokenEnd + 4), implicitOR)]
};
} else {
let padding = 0;
if (str.startsWith(' or', tokenEnd)) {
padding = 3;
}
} else if (str.startsWith(' or', tokenEnd)) {
return <ORSearchQuery>{
type: SearchQueryTypes.OR,
list: [SearchQueryDTO.parse(str.slice(0, tokenEnd)), // trim brackets
SearchQueryDTO.parse(str.slice(tokenEnd + padding))]
list: [SearchQueryDTO.parse(str.slice(0, tokenEnd), implicitOR), // trim brackets
SearchQueryDTO.parse(str.slice(tokenEnd + 3), implicitOR)]
};
} else { // Relation cannot be detected
return <SearchListQuery>{
type: implicitOR === true ? SearchQueryTypes.OR : SearchQueryTypes.UNKNOWN_RELATION,
list: [SearchQueryDTO.parse(str.slice(0, tokenEnd), implicitOR), // trim brackets
SearchQueryDTO.parse(str.slice(tokenEnd), implicitOR)]
};
}
}
if (str.startsWith('some-of:') ||
new RegExp(/^\d*-of:/).test(str)) {
const prefix = str.startsWith('some-of:') ? 'some-of:' : new RegExp(/^\d*-of:/).exec(str)[0];
let tmpList: any = SearchQueryDTO.parse(str.slice(prefix.length + 1, -1)); // trim brackets
let tmpList: any = SearchQueryDTO.parse(str.slice(prefix.length + 1, -1), false); // trim brackets
// console.log(JSON.stringify(tmpList, null, 4));
const unfoldList = (q: SearchListQuery): SearchQueryDTO[] => {
if (q.list) {
return [].concat.apply([], q.list.map(e => unfoldList(<any>e))); // flatten array
if (q.type === SearchQueryTypes.UNKNOWN_RELATION) {
return [].concat.apply([], q.list.map(e => unfoldList(<any>e))); // flatten array
} else {
q.list.forEach(e => unfoldList(<any>e));
}
}
return [q];
};

View File

@ -792,7 +792,7 @@ describe('SearchManager', (sqlHelper: SQLTestHelper) => {
it('should search date', async () => {
const sm = new SearchManager();
let query: any = <FromDateSearch>{value: 0, type: SearchQueryTypes.from_date};
let query: any = <ToDateSearch>{value: 0, type: SearchQueryTypes.to_date};
expect(Utils.clone(await sm.search(query)))
.to.deep.equalInAnyOrder(removeDir(<SearchResultDTO>{
@ -803,15 +803,15 @@ describe('SearchManager', (sqlHelper: SQLTestHelper) => {
resultOverflow: false
}));
query = <ToDateSearch>{
value: p.metadata.creationDate, type: SearchQueryTypes.to_date
query = <FromDateSearch>{
value: p.metadata.creationDate, type: SearchQueryTypes.from_date
};
expect(Utils.clone(await sm.search(query)))
.to.deep.equalInAnyOrder(removeDir(<SearchResultDTO>{
searchQuery: query,
directories: [],
media: [p],
media: [p, v],
metaFile: [],
resultOverflow: false
}));
@ -826,7 +826,7 @@ describe('SearchManager', (sqlHelper: SQLTestHelper) => {
.to.deep.equalInAnyOrder(removeDir(<SearchResultDTO>{
searchQuery: query,
directories: [],
media: [p2, p_faceLess, p4, v],
media: [p2, p_faceLess, p4],
metaFile: [],
resultOverflow: false
}));
@ -851,7 +851,7 @@ describe('SearchManager', (sqlHelper: SQLTestHelper) => {
it('should search rating', async () => {
const sm = new SearchManager();
let query: MinRatingSearch | MaxRatingSearch = <MinRatingSearch>{value: 0, type: SearchQueryTypes.min_rating};
let query: MinRatingSearch | MaxRatingSearch = <MaxRatingSearch>{value: 0, type: SearchQueryTypes.max_rating};
expect(Utils.clone(await sm.search(query)))
@ -888,7 +888,7 @@ describe('SearchManager', (sqlHelper: SQLTestHelper) => {
.to.deep.equalInAnyOrder(removeDir(<SearchResultDTO>{
searchQuery: query,
directories: [],
media: [p2],
media: [p2, p_faceLess],
metaFile: [],
resultOverflow: false
}));
@ -898,7 +898,7 @@ describe('SearchManager', (sqlHelper: SQLTestHelper) => {
.to.deep.equalInAnyOrder(removeDir(<SearchResultDTO>{
searchQuery: query,
directories: [],
media: [p, p_faceLess],
media: [p],
metaFile: [],
resultOverflow: false
}));
@ -909,7 +909,7 @@ describe('SearchManager', (sqlHelper: SQLTestHelper) => {
const sm = new SearchManager();
let query: MinResolutionSearch | MaxResolutionSearch =
<MinResolutionSearch>{value: 0, type: SearchQueryTypes.min_resolution};
<MaxResolutionSearch>{value: 0, type: SearchQueryTypes.max_resolution};
expect(Utils.clone(await sm.search(query)))
.to.deep.equalInAnyOrder(removeDir(<SearchResultDTO>{
@ -930,27 +930,28 @@ describe('SearchManager', (sqlHelper: SQLTestHelper) => {
resultOverflow: false
}));
query = <MinResolutionSearch>{value: 2, type: SearchQueryTypes.min_resolution};
query = <MinResolutionSearch>{value: 3, type: SearchQueryTypes.min_resolution};
expect(Utils.clone(await sm.search(query)))
.to.deep.equalInAnyOrder(removeDir(<SearchResultDTO>{
searchQuery: query,
directories: [],
media: [p2, p_faceLess],
media: [p4],
metaFile: [],
resultOverflow: false
}));
query = <MinResolutionSearch>{value: 3, negate: true, type: SearchQueryTypes.min_resolution};
expect(Utils.clone(await sm.search(query)))
.to.deep.equalInAnyOrder(removeDir(<SearchResultDTO>{
searchQuery: query,
directories: [],
media: [p, p2, p_faceLess, v],
metaFile: [],
resultOverflow: false
}));
query = <MaxResolutionSearch>{value: 3, negate: true, type: SearchQueryTypes.max_resolution};
expect(Utils.clone(await sm.search(query)))
.to.deep.equalInAnyOrder(removeDir(<SearchResultDTO>{
searchQuery: query,
directories: [],
media: [p, v, p4],
metaFile: [],
resultOverflow: false
}));
query = <MinResolutionSearch>{value: 3, negate: true, type: SearchQueryTypes.min_resolution};
expect(Utils.clone(await sm.search(query)))
.to.deep.equalInAnyOrder(removeDir(<SearchResultDTO>{
searchQuery: query,

View File

@ -13,6 +13,7 @@ import {
SearchQueryTypes,
SomeOfSearchQuery,
TextSearch,
TextSearchQueryMatchTypes,
ToDateSearch
} from '../../../src/common/entities/SearchQueryDTO';
@ -33,6 +34,11 @@ describe('SearchQueryDTO', () => {
check(<TextSearch>{type: SearchQueryTypes.caption, text: 'caption'});
check(<TextSearch>{type: SearchQueryTypes.file_name, text: 'filename'});
check(<TextSearch>{type: SearchQueryTypes.position, text: 'New York'});
check(<TextSearch>{
type: SearchQueryTypes.position,
matchType: TextSearchQueryMatchTypes.exact_match,
text: 'New York'
});
});
it('Date search', () => {
@ -62,6 +68,18 @@ describe('SearchQueryDTO', () => {
<TextSearch>{type: SearchQueryTypes.position, text: 'New York'}
]
});
check(<ANDSearchQuery>{
type: SearchQueryTypes.AND,
list: [
<TextSearch>{type: SearchQueryTypes.keyword, text: 'big boom'},
<TextSearch>{
type: SearchQueryTypes.position,
matchType: TextSearchQueryMatchTypes.exact_match,
text: 'New York'
}
]
});
check(<ANDSearchQuery>{
type: SearchQueryTypes.AND,
list: [
@ -75,6 +93,21 @@ describe('SearchQueryDTO', () => {
}
]
});
check(<ANDSearchQuery>{
type: SearchQueryTypes.AND,
list: [
<SomeOfSearchQuery>{
type: SearchQueryTypes.SOME_OF,
min: 2,
list: [
<TextSearch>{type: SearchQueryTypes.keyword, text: 'big boom'},
<TextSearch>{type: SearchQueryTypes.position, text: 'New York'},
<TextSearch>{type: SearchQueryTypes.caption, text: 'caption test'}
]
},
<TextSearch>{type: SearchQueryTypes.position, text: 'New York'}
]
});
});
it('Or search', () => {
check(<ORSearchQuery>{
@ -106,6 +139,21 @@ describe('SearchQueryDTO', () => {
<TextSearch>{type: SearchQueryTypes.position, text: 'New York'}
]
});
check(<SomeOfSearchQuery>{
type: SearchQueryTypes.SOME_OF,
list: [
<TextSearch>{
type: SearchQueryTypes.keyword,
matchType: TextSearchQueryMatchTypes.exact_match,
text: 'big boom'
},
<TextSearch>{
type: SearchQueryTypes.position,
matchType: TextSearchQueryMatchTypes.exact_match,
text: 'New York'
},
]
});
check(<SomeOfSearchQuery>{
type: SearchQueryTypes.SOME_OF,
min: 2,