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

Adopting date pattern search to MySQL #660

This commit is contained in:
Patrik J. Braun 2023-06-24 13:11:56 +02:00
parent 5793655e8d
commit 3fb31f17a8
2 changed files with 47 additions and 25 deletions

View File

@ -161,7 +161,7 @@ export class SearchManager {
.groupBy( .groupBy(
'photo.metadata.positionData.country, photo.metadata.positionData.state, photo.metadata.positionData.city' 'photo.metadata.positionData.country, photo.metadata.positionData.state, photo.metadata.positionData.city'
) )
.limit(Config.Search.AutoComplete.ItemsPerCategory.position ) .limit(Config.Search.AutoComplete.ItemsPerCategory.position)
.getRawMany() .getRawMany()
) )
.filter((pm): boolean => !!pm) .filter((pm): boolean => !!pm)
@ -658,6 +658,9 @@ export class SearchManager {
}); });
case SearchQueryTypes.date_pattern: { case SearchQueryTypes.date_pattern: {
if (directoryOnly) {
throw new Error('not supported in directoryOnly mode');
}
const tq = query as DatePatternSearch; const tq = query as DatePatternSearch;
return new Brackets((q): unknown => { return new Brackets((q): unknown => {
@ -719,33 +722,40 @@ export class SearchManager {
const relationTop = tq.negate ? '>' : '<='; const relationTop = tq.negate ? '>' : '<=';
const relationBottom = tq.negate ? '<=' : '>'; const relationBottom = tq.negate ? '<=' : '>';
const addWhere = (duration: string) => {
if (Config.Database.type === DatabaseType.sqlite) {
q.where(
`CAST(strftime('${duration}',media.metadataCreationDate/1000, 'unixepoch') AS INTEGER) ${relationTop} CAST(strftime('${duration}','now') AS INTEGER)`
).andWhere(`CAST(strftime('${duration}',media.metadataCreationDate/1000, 'unixepoch') AS INTEGER) ${relationBottom} CAST(strftime('${duration}','now','-:diff${queryId} day') AS INTEGER)`,
textParam);
} else {
q.where(
`CAST(FROM_UNIXTIME(media.metadataCreationDate/1000, '${duration}') AS SIGNED) ${relationTop} CAST(DATE_FORMAT(CURDATE(),'${duration}') AS SIGNED)`
).andWhere(`CAST(FROM_UNIXTIME(media.metadataCreationDate/1000, '${duration}') AS SIGNED) ${relationBottom} CAST(DATE_FORMAT((DATE_ADD(curdate(), INTERVAL -:diff${queryId} DAY)),'${duration}') AS SIGNED)`,
textParam);
}
};
switch (tq.frequency) { switch (tq.frequency) {
case DatePatternFrequency.every_year: case DatePatternFrequency.every_year:
if (tq.daysLength >= 365) { if (tq.daysLength >= 365) {
return q; return q;
} }
q.where( addWhere('%j');
`CAST(strftime('%j',media.metadataCreationDate/1000, 'unixepoch') AS INTEGER) ${relationTop} CAST(strftime('%j','now') AS INTEGER)`
).andWhere(`CAST(strftime('%j',media.metadataCreationDate/1000, 'unixepoch') AS INTEGER) ${relationBottom} CAST(strftime('%j','now','-:diff${queryId} day') AS INTEGER)`,
textParam);
break; break;
case DatePatternFrequency.every_month: case DatePatternFrequency.every_month:
if (tq.daysLength >= 31) { if (tq.daysLength >= 31) {
return q; return q;
} }
q.where( addWhere('%d');
`CAST(strftime('%d',media.metadataCreationDate/1000, 'unixepoch') AS INTEGER) ${relationTop} CAST(strftime('%d','now') AS INTEGER)`
).andWhere(`CAST(strftime('%d',media.metadataCreationDate/1000, 'unixepoch') AS INTEGER) ${relationBottom} CAST(strftime('%d','now','-:diff${queryId} day') AS INTEGER)`,
textParam);
break; break;
case DatePatternFrequency.every_week: case DatePatternFrequency.every_week:
if (tq.daysLength >= 7) { if (tq.daysLength >= 7) {
return q; return q;
} }
q.where( addWhere('%w');
`CAST(strftime('%w',media.metadataCreationDate/1000, 'unixepoch') AS INTEGER) ${relationTop} CAST(strftime('%w','now') AS INTEGER)`
).andWhere(`CAST(strftime('%w',media.metadataCreationDate/1000, 'unixepoch') AS INTEGER) ${relationBottom} CAST(strftime('%w','now','-:diff${queryId} day') AS INTEGER)`,
textParam);
break; break;
} }

View File

@ -118,6 +118,7 @@ describe('SearchManager', (sqlHelper: DBTestHelper) => {
p4.metadata.creationDate = Date.now() - 60 * 60 * 24 * 366 * 1000; p4.metadata.creationDate = Date.now() - 60 * 60 * 24 * 366 * 1000;
const pFaceLessTmp = TestHelper.getPhotoEntry3(subDir); const pFaceLessTmp = TestHelper.getPhotoEntry3(subDir);
delete pFaceLessTmp.metadata.faces; delete pFaceLessTmp.metadata.faces;
pFaceLessTmp.metadata.creationDate = Date.now() - 60 * 60 * 24 * 32 * 1000;
dir = await DBTestHelper.persistTestDir(directory); dir = await DBTestHelper.persistTestDir(directory);
@ -189,19 +190,14 @@ describe('SearchManager', (sqlHelper: DBTestHelper) => {
Config.Search.AutoComplete.ItemsPerCategory.maxItems = 1; Config.Search.AutoComplete.ItemsPerCategory.maxItems = 1;
expect((await sm.autocomplete('a', SearchQueryTypes.any_text))).to.deep.equalInAnyOrder([ expect((await sm.autocomplete('a', SearchQueryTypes.any_text))).to.deep.equalInAnyOrder([
new AutoCompleteItem('Ajan Kloss', SearchQueryTypes.position), new AutoCompleteItem('Han Solo', SearchQueryTypes.person),
new AutoCompleteItem('Tipoca City', SearchQueryTypes.position), new AutoCompleteItem('Han Solo\'s dice', SearchQueryTypes.caption),
new AutoCompleteItem('Amber stone', SearchQueryTypes.caption), new AutoCompleteItem('Research City', SearchQueryTypes.position),
new AutoCompleteItem('Millennium falcon', SearchQueryTypes.caption), new AutoCompleteItem('death star', SearchQueryTypes.keyword),
new AutoCompleteItem('star wars', SearchQueryTypes.keyword), new AutoCompleteItem('wars dir', SearchQueryTypes.directory)]);
new AutoCompleteItem('Anakin Skywalker', SearchQueryTypes.person),
new AutoCompleteItem('Obivan Kenobi', SearchQueryTypes.person),
new AutoCompleteItem('Castilon', SearchQueryTypes.position),
new AutoCompleteItem('Devaron', SearchQueryTypes.position),
new AutoCompleteItem('Jedha', SearchQueryTypes.position),
new AutoCompleteItem('wars dir', SearchQueryTypes.directory),
new AutoCompleteItem('The Phantom Menace', SearchQueryTypes.directory)]);
Config.Search.AutoComplete.ItemsPerCategory.maxItems = 5; Config.Search.AutoComplete.ItemsPerCategory.maxItems = 5;
Config.Search.AutoComplete.ItemsPerCategory.fileName = 5;
Config.Search.AutoComplete.ItemsPerCategory.fileName = 5;
expect((await sm.autocomplete('sw', SearchQueryTypes.any_text))).to.deep.equalInAnyOrder([ expect((await sm.autocomplete('sw', SearchQueryTypes.any_text))).to.deep.equalInAnyOrder([
new AutoCompleteItem('sw1.jpg', SearchQueryTypes.file_name), new AutoCompleteItem('sw1.jpg', SearchQueryTypes.file_name),
@ -991,6 +987,22 @@ describe('SearchManager', (sqlHelper: DBTestHelper) => {
resultOverflow: false resultOverflow: false
} as SearchResultDTO)); } as SearchResultDTO));
query = {
daysLength: 3,
agoNumber: 1,
frequency: DatePatternFrequency.months_ago,
type: SearchQueryTypes.date_pattern
} as DatePatternSearch;
expect(Utils.clone(await sm.search(query)))
.to.deep.equalInAnyOrder(removeDir({
searchQuery: query,
directories: [],
media: [pFaceLess],
metaFile: [],
resultOverflow: false
} as SearchResultDTO));
query = { query = {
daysLength: 366, daysLength: 366,
frequency: DatePatternFrequency.every_year, frequency: DatePatternFrequency.every_year,