1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2024-12-02 09:12:07 +02:00

Adding count and precalculated preview to saved search #45

This commit is contained in:
Patrik J. Braun 2021-05-31 19:55:27 +02:00
parent 2e12af46d1
commit 597d179f7d
12 changed files with 70 additions and 21 deletions

View File

@ -23,4 +23,9 @@ export interface IAlbumManager {
* Returns with all albums
*/
getAlbums(): Promise<AlbumBaseDTO[]>;
/**
* Updates previews and album counts
*/
onGalleryIndexUpdate(): Promise<void>;
}

View File

@ -9,14 +9,6 @@ import {SavedSearchEntity} from './enitites/album/SavedSearchEntity';
import {IAlbumManager} from '../interfaces/IAlbumManager';
export class AlbumManager implements IAlbumManager {
private static async fillPreviewToAlbum(album: AlbumBaseDTO): Promise<void> {
if (!(album as SavedSearchDTO).searchQuery) {
throw new Error('no search query present');
}
album.preview = await (ObjectManagers.getInstance().SearchManager as ISQLSearchManager)
.getPreview((album as SavedSearchDTO).searchQuery);
}
public async addIfNotExistSavedSearch(name: string, searchQuery: SearchQueryDTO, lockedAlbum: boolean): Promise<void> {
const connection = await SQLConnection.getConnection();
const album = await connection.getRepository(SavedSearchEntity)
@ -24,12 +16,13 @@ export class AlbumManager implements IAlbumManager {
if (album) {
return;
}
this.addSavedSearch(name, searchQuery, lockedAlbum);
await this.addSavedSearch(name, searchQuery, lockedAlbum);
}
public async addSavedSearch(name: string, searchQuery: SearchQueryDTO, lockedAlbum?: boolean): Promise<void> {
const connection = await SQLConnection.getConnection();
await connection.getRepository(SavedSearchEntity).insert({name, searchQuery, locked: lockedAlbum});
const a = await connection.getRepository(SavedSearchEntity).save({name, searchQuery, locked: lockedAlbum});
await this.updateAlbum(a);
}
public async deleteAlbum(id: number): Promise<void> {
@ -46,12 +39,36 @@ export class AlbumManager implements IAlbumManager {
public async getAlbums(): Promise<AlbumBaseDTO[]> {
const connection = await SQLConnection.getConnection();
const albums = await connection.getRepository(AlbumBaseEntity).find();
return await connection.getRepository(AlbumBaseEntity).find({
relations: ['preview', 'preview.directory']
});
}
public async onGalleryIndexUpdate(): Promise<void> {
await this.updateAlbums();
}
private async updateAlbums(): Promise<void> {
const albums = await this.getAlbums();
for (const a of albums) {
await AlbumManager.fillPreviewToAlbum(a);
await this.updateAlbum(a as SavedSearchEntity);
}
return albums;
}
private async updateAlbum(album: SavedSearchEntity): Promise<void> {
const connection = await SQLConnection.getConnection();
const preview = await (ObjectManagers.getInstance().SearchManager as ISQLSearchManager)
.getPreview((album as SavedSearchDTO).searchQuery);
const count = await (ObjectManagers.getInstance().SearchManager as ISQLSearchManager)
.getCount((album as SavedSearchDTO).searchQuery);
await connection
.createQueryBuilder()
.update(AlbumBaseEntity)
.set({preview, count})
.where('id = :id', {id: album.id})
.execute();
}
}

View File

@ -14,4 +14,5 @@ export interface ISQLSearchManager extends ISearchManager {
// "Protected" functions. only called from other Managers, not from middlewares
getPreview(query: SearchQueryDTO): Promise<MediaDTO>;
getCount(query: SearchQueryDTO): Promise<number>;
}

View File

@ -370,6 +370,7 @@ export class IndexingManager implements IIndexingManager {
await this.saveMedia(connection, currentDirId, scannedDirectory.media);
await this.saveMetaFiles(connection, currentDirId, scannedDirectory);
await ObjectManagers.getInstance().PersonManager.onGalleryIndexUpdate();
await ObjectManagers.getInstance().AlbumManager.onGalleryIndexUpdate();
await ObjectManagers.getInstance().VersionManager.updateDataVersion();
await IndexingManager.processServerSidePG2Conf(serverSideConfigs);
} finally {

View File

@ -237,6 +237,18 @@ export class SearchManager implements ISQLSearchManager {
.getOne();
}
public async getCount(queryIN: SearchQueryDTO): Promise<number> {
const query = await this.prepareQuery(queryIN);
const connection = await SQLConnection.getConnection();
return await connection
.getRepository(MediaEntity)
.createQueryBuilder('media')
.innerJoin('media.directory', 'directory')
.where(this.buildWhereQuery(query))
.getCount();
}
protected flattenSameOfQueries(query: SearchQueryDTO): SearchQueryDTO {
switch (query.type) {
case SearchQueryTypes.AND:

View File

@ -1,4 +1,4 @@
import {Column, Entity, Index, PrimaryGeneratedColumn, TableInheritance} from 'typeorm';
import {Column, Entity, Index, ManyToOne, PrimaryGeneratedColumn, TableInheritance} from 'typeorm';
import {MediaEntity} from '../MediaEntity';
import {columnCharsetCS} from '../EntityUtils';
import {AlbumBaseDTO} from '../../../../../../common/entities/album/AlbumBaseDTO';
@ -21,7 +21,10 @@ export class AlbumBaseEntity implements AlbumBaseDTO {
@Column({default: false})
locked: boolean;
// not saving to database, it is only assigned when querying the DB
@Column('int', {unsigned: true, default: 0})
count: number;
@ManyToOne(type => MediaEntity, {onDelete: 'SET NULL', nullable: true})
public preview: MediaEntity;
}

View File

@ -1,4 +1,4 @@
/**
* This version indicates that the SQL sql/entities/*Entity.ts files got changed and the db needs to be recreated
*/
export const DataStructureVersion = 24;
export const DataStructureVersion = 25;

View File

@ -4,5 +4,6 @@ export interface AlbumBaseDTO {
id: number;
name: string;
preview?: PreviewPhotoDTO;
count: number;
locked: boolean;
}

View File

@ -6,6 +6,7 @@ export interface SavedSearchDTO extends AlbumBaseDTO {
id: number;
name: string;
preview?: PreviewPhotoDTO;
count: number;
locked: boolean;
searchQuery: SearchQueryDTO;

View File

@ -18,7 +18,7 @@
<!--Info box -->
<div class="info">
{{album.name}}
{{album.name}} ({{album.count}})
<span *ngIf="CanUpdate && !album.locked"
(click)="deleteAlbum($event)"
class="info-button delete oi oi-trash float-right"></span>

View File

@ -119,6 +119,7 @@ describe('AlbumManager', (sqlHelper: DBTestHelper) => {
id: 1,
name: 'Test Album',
locked: false,
count: 0,
searchQuery: query
} as SavedSearchDTO]);
});
@ -138,12 +139,14 @@ describe('AlbumManager', (sqlHelper: DBTestHelper) => {
id: 1,
name: 'Test Album',
locked: false,
count: 0,
searchQuery: query
} as SavedSearchDTO,
{
id: 2,
name: 'Test Album2',
locked: true,
count: 0,
searchQuery: query
} as SavedSearchDTO]);
@ -152,6 +155,7 @@ describe('AlbumManager', (sqlHelper: DBTestHelper) => {
id: 2,
name: 'Test Album2',
locked: true,
count: 0,
searchQuery: query
} as SavedSearchDTO]);
@ -165,6 +169,7 @@ describe('AlbumManager', (sqlHelper: DBTestHelper) => {
id: 2,
name: 'Test Album2',
locked: true,
count: 0,
searchQuery: query
} as SavedSearchDTO]);
});
@ -182,6 +187,7 @@ describe('AlbumManager', (sqlHelper: DBTestHelper) => {
name: 'Test Album',
searchQuery: query,
locked: false,
count: 1,
preview: toAlbumPreview(p)
} as SavedSearchDTO]));

View File

@ -14,11 +14,11 @@ import {ObjectManagers} from '../../../../../src/backend/model/ObjectManagers';
import {DBTestHelper} from '../../../DBTestHelper';
import {DiskMangerWorker} from '../../../../../src/backend/model/threading/DiskMangerWorker';
import {ReIndexingSensitivity} from '../../../../../src/common/config/private/PrivateConfig';
import {AlbumManager} from '../../../../../src/backend/model/database/sql/AlbumManager';
import {SearchQueryTypes, TextSearch, TextSearchQueryMatchTypes} from '../../../../../src/common/entities/SearchQueryDTO';
import {ProjectPath} from '../../../../../src/backend/ProjectPath';
import * as path from 'path';
import {DiskManager} from '../../../../../src/backend/model/DiskManger';
import {AlbumManager} from '../../../../../src/backend/model/database/sql/AlbumManager';
const deepEqualInAnyOrder = require('deep-equal-in-any-order');
const chai = require('chai');
@ -47,7 +47,7 @@ class IndexingManagerTest extends IndexingManager {
}
public async saveToDB(scannedDirectory: DirectoryDTO): Promise<void> {
return super.saveToDB(scannedDirectory);
return await super.saveToDB(scannedDirectory);
}
}
@ -591,16 +591,18 @@ describe('IndexingManager', (sqlHelper: DBTestHelper) => {
const am = new AlbumManager();
const dir = await DiskManager.scanDirectory('/');
await im.saveToDB(dir);
const albums = await am.getAlbums();
// expect(albums[0].preview).to.be.an('object');
expect(albums[0].preview).to.be.an('object');
delete albums[0].preview;
expect(albums).to.be.equalInAnyOrder([
{
id: 1,
name: 'Alvin',
locked: true,
count: 1,
searchQuery: {
type: SearchQueryTypes.person,
text: 'Alvin',