You've already forked pigallery2
mirror of
https://github.com/bpatrik/pigallery2.git
synced 2025-12-01 22:52:06 +02:00
bug fixing
This commit is contained in:
@@ -4,9 +4,8 @@ import {NextFunction, Request, Response} from "express";
|
||||
import {Error, ErrorCodes} from "../../common/entities/Error";
|
||||
import {DirectoryDTO} from "../../common/entities/DirectoryDTO";
|
||||
import {ObjectManagerRepository} from "../model/ObjectManagerRepository";
|
||||
import {AutoCompleteItem, SearchTypes} from "../../common/entities/AutoCompleteItem";
|
||||
import {SearchTypes} from "../../common/entities/AutoCompleteItem";
|
||||
import {ContentWrapper} from "../../common/entities/ConentWrapper";
|
||||
import {SearchResultDTO} from "../../common/entities/SearchResult";
|
||||
import {PhotoDTO} from "../../common/entities/PhotoDTO";
|
||||
import {ProjectPath} from "../ProjectPath";
|
||||
import {Logger} from "../Logger";
|
||||
@@ -92,7 +91,7 @@ export class GalleryMWs {
|
||||
}
|
||||
|
||||
|
||||
public static search(req: Request, res: Response, next: NextFunction) {
|
||||
public static async search(req: Request, res: Response, next: NextFunction) {
|
||||
if (Config.Client.Search.searchEnabled === false) {
|
||||
return next();
|
||||
}
|
||||
@@ -105,18 +104,21 @@ export class GalleryMWs {
|
||||
if (req.query.type) {
|
||||
type = parseInt(req.query.type);
|
||||
}
|
||||
try {
|
||||
const result = await ObjectManagerRepository.getInstance().SearchManager.search(req.params.text, type);
|
||||
|
||||
ObjectManagerRepository.getInstance().SearchManager.search(req.params.text, type, (err, result: SearchResultDTO) => {
|
||||
if (err || !result) {
|
||||
return next(new Error(ErrorCodes.GENERAL_ERROR, err));
|
||||
}
|
||||
result.directories.forEach(dir => dir.photos = dir.photos || []);
|
||||
req.resultPipe = new ContentWrapper(null, result);
|
||||
return next();
|
||||
});
|
||||
} catch (err) {
|
||||
|
||||
Logger.warn(LOG_TAG, "Error during searching", err);
|
||||
console.error(err);
|
||||
return next(new Error(ErrorCodes.GENERAL_ERROR, err));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static instantSearch(req: Request, res: Response, next: NextFunction) {
|
||||
public static async instantSearch(req: Request, res: Response, next: NextFunction) {
|
||||
if (Config.Client.Search.instantSearchEnabled === false) {
|
||||
return next();
|
||||
}
|
||||
@@ -125,17 +127,20 @@ export class GalleryMWs {
|
||||
return next();
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await ObjectManagerRepository.getInstance().SearchManager.instantSearch(req.params.text);
|
||||
|
||||
ObjectManagerRepository.getInstance().SearchManager.instantSearch(req.params.text, (err, result: SearchResultDTO) => {
|
||||
if (err || !result) {
|
||||
return next(new Error(ErrorCodes.GENERAL_ERROR, err));
|
||||
}
|
||||
result.directories.forEach(dir => dir.photos = dir.photos || []);
|
||||
req.resultPipe = new ContentWrapper(null, result);
|
||||
return next();
|
||||
});
|
||||
} catch (err) {
|
||||
Logger.warn(LOG_TAG, "Error during searching", err);
|
||||
console.error(err);
|
||||
return next(new Error(ErrorCodes.GENERAL_ERROR, err));
|
||||
}
|
||||
}
|
||||
|
||||
public static autocomplete(req: Request, res: Response, next: NextFunction) {
|
||||
public static async autocomplete(req: Request, res: Response, next: NextFunction) {
|
||||
if (Config.Client.Search.autocompleteEnabled === false) {
|
||||
return next();
|
||||
}
|
||||
@@ -143,13 +148,15 @@ export class GalleryMWs {
|
||||
return next();
|
||||
}
|
||||
|
||||
ObjectManagerRepository.getInstance().SearchManager.autocomplete(req.params.text, (err, items: Array<AutoCompleteItem>) => {
|
||||
if (err || !items) {
|
||||
return next(new Error(ErrorCodes.GENERAL_ERROR, err));
|
||||
}
|
||||
req.resultPipe = items;
|
||||
try {
|
||||
req.resultPipe = await ObjectManagerRepository.getInstance().SearchManager.autocomplete(req.params.text);
|
||||
return next();
|
||||
});
|
||||
} catch (err) {
|
||||
Logger.warn(LOG_TAG, "Error during searching", err);
|
||||
console.error(err);
|
||||
return next(new Error(ErrorCodes.GENERAL_ERROR, err));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {AutoCompleteItem, SearchTypes} from "../../../common/entities/AutoCompleteItem";
|
||||
import {SearchResultDTO} from "../../../common/entities/SearchResult";
|
||||
export interface ISearchManager {
|
||||
autocomplete(text: string, cb: (error: any, result: Array<AutoCompleteItem>) => void): void;
|
||||
search(text: string, searchType: SearchTypes, cb: (error: any, result: SearchResultDTO) => void): void;
|
||||
instantSearch(text: string, cb: (error: any, result: SearchResultDTO) => void): void;
|
||||
autocomplete(text: string): Promise<AutoCompleteItem[]>;
|
||||
search(text: string, searchType: SearchTypes): Promise<SearchResultDTO>;
|
||||
instantSearch(text: string): Promise<SearchResultDTO>;
|
||||
isSupported(): boolean;
|
||||
}
|
||||
|
||||
@@ -3,22 +3,22 @@ import {ISearchManager} from "../interfaces/ISearchManager";
|
||||
import {SearchResultDTO} from "../../../common/entities/SearchResult";
|
||||
|
||||
export class SearchManager implements ISearchManager {
|
||||
autocomplete(text: string): Promise<AutoCompleteItem[]> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
search(text: string, searchType: SearchTypes): Promise<SearchResultDTO> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
instantSearch(text: string): Promise<SearchResultDTO> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
isSupported(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
autocomplete(text: string, cb: (error: any, result: Array<AutoCompleteItem>) => void) {
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
|
||||
search(text: string, searchType: SearchTypes, cb: (error: any, result: SearchResultDTO) => void) {
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
|
||||
instantSearch(text: string, cb: (error: any, result: SearchResultDTO) => void) {
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -12,163 +12,157 @@ export class SearchManager implements ISearchManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
autocomplete(text: string, cb: (error: any, result: Array<AutoCompleteItem>) => void) {
|
||||
async autocomplete(text: string) {
|
||||
|
||||
MySQLConnection.getConnection().then(async connection => {
|
||||
try {
|
||||
let result: Array<AutoCompleteItem> = [];
|
||||
let photoRepository = connection.getRepository(PhotoEntity);
|
||||
let directoryRepository = connection.getRepository(DirectoryEntity);
|
||||
const connection = await MySQLConnection.getConnection();
|
||||
|
||||
let result: Array<AutoCompleteItem> = [];
|
||||
let photoRepository = connection.getRepository(PhotoEntity);
|
||||
let directoryRepository = connection.getRepository(DirectoryEntity);
|
||||
|
||||
|
||||
(await photoRepository
|
||||
.createQueryBuilder('photo')
|
||||
.select('DISTINCT(photo.metadataKeywords)')
|
||||
.where('photo.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
|
||||
.setLimit(5)
|
||||
.getRawMany())
|
||||
.map(r => <Array<string>>JSON.parse(r.metadataKeywords))
|
||||
.forEach(keywords => {
|
||||
result = result.concat(this.encapsulateAutoComplete(keywords.filter(k => k.toLowerCase().indexOf(text.toLowerCase()) != -1), SearchTypes.keyword));
|
||||
});
|
||||
(await photoRepository
|
||||
.createQueryBuilder('photo')
|
||||
.select('DISTINCT(photo.metadataKeywords)')
|
||||
.where('photo.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
|
||||
.setLimit(5)
|
||||
.getRawMany())
|
||||
.map(r => <Array<string>>JSON.parse(r.metadataKeywords))
|
||||
.forEach(keywords => {
|
||||
result = result.concat(this.encapsulateAutoComplete(keywords.filter(k => k.toLowerCase().indexOf(text.toLowerCase()) != -1), SearchTypes.keyword));
|
||||
});
|
||||
|
||||
|
||||
(await photoRepository
|
||||
.createQueryBuilder('photo')
|
||||
.select('DISTINCT(photo.metadataPositionData)')
|
||||
.where('photo.metadata.positionData LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
|
||||
.setLimit(5)
|
||||
.getRawMany())
|
||||
.map(r => <PositionMetaData>JSON.parse(r.metadataPositionData))
|
||||
.map(pm => <Array<string>>[pm.city || "", pm.country || "", pm.state || ""])
|
||||
.forEach(positions => {
|
||||
result = result.concat(this.encapsulateAutoComplete(positions.filter(p => p.toLowerCase().indexOf(text.toLowerCase()) != -1), SearchTypes.position));
|
||||
});
|
||||
(await photoRepository
|
||||
.createQueryBuilder('photo')
|
||||
.select('DISTINCT(photo.metadataPositionData)')
|
||||
.where('photo.metadata.positionData LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
|
||||
.setLimit(5)
|
||||
.getRawMany())
|
||||
.map(r => <PositionMetaData>JSON.parse(r.metadataPositionData))
|
||||
.filter(pm => !!pm)
|
||||
.map(pm => <Array<string>>[pm.city || "", pm.country || "", pm.state || ""])
|
||||
.forEach(positions => {
|
||||
result = result.concat(this.encapsulateAutoComplete(positions.filter(p => p.toLowerCase().indexOf(text.toLowerCase()) != -1), SearchTypes.position));
|
||||
});
|
||||
|
||||
|
||||
result = result.concat(this.encapsulateAutoComplete((await photoRepository
|
||||
.createQueryBuilder('photo')
|
||||
.select('DISTINCT(photo.name)')
|
||||
.where('photo.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
|
||||
.setLimit(5)
|
||||
.getRawMany())
|
||||
.map(r => r.name), SearchTypes.image));
|
||||
result = result.concat(this.encapsulateAutoComplete((await photoRepository
|
||||
.createQueryBuilder('photo')
|
||||
.select('DISTINCT(photo.name)')
|
||||
.where('photo.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
|
||||
.setLimit(5)
|
||||
.getRawMany())
|
||||
.map(r => r.name), SearchTypes.image));
|
||||
|
||||
result = result.concat(this.encapsulateAutoComplete((await directoryRepository
|
||||
.createQueryBuilder('dir')
|
||||
.select('DISTINCT(dir.name)')
|
||||
.where('dir.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
|
||||
.setLimit(5)
|
||||
.getRawMany())
|
||||
.map(r => r.name), SearchTypes.directory));
|
||||
result = result.concat(this.encapsulateAutoComplete((await directoryRepository
|
||||
.createQueryBuilder('dir')
|
||||
.select('DISTINCT(dir.name)')
|
||||
.where('dir.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
|
||||
.setLimit(5)
|
||||
.getRawMany())
|
||||
.map(r => r.name), SearchTypes.directory));
|
||||
|
||||
|
||||
return cb(null, this.autoCompleteItemsUnique(result));
|
||||
} catch (error) {
|
||||
return cb(error, null);
|
||||
}
|
||||
|
||||
}).catch((error) => {
|
||||
return cb(error, null);
|
||||
});
|
||||
return this.autoCompleteItemsUnique(result);
|
||||
}
|
||||
|
||||
search(text: string, searchType: SearchTypes, cb: (error: any, result: SearchResultDTO) => void) {
|
||||
MySQLConnection.getConnection().then(async connection => {
|
||||
async search(text: string, searchType: SearchTypes) {
|
||||
const connection = await MySQLConnection.getConnection();
|
||||
|
||||
let result: SearchResultDTO = <SearchResultDTO>{
|
||||
searchText: text,
|
||||
searchType: searchType,
|
||||
directories: [],
|
||||
photos: []
|
||||
};
|
||||
let result: SearchResultDTO = <SearchResultDTO>{
|
||||
searchText: text,
|
||||
searchType: searchType,
|
||||
directories: [],
|
||||
photos: []
|
||||
};
|
||||
|
||||
let query = connection
|
||||
.getRepository(PhotoEntity)
|
||||
.createQueryBuilder("photo");
|
||||
let query = connection
|
||||
.getRepository(PhotoEntity)
|
||||
.createQueryBuilder("photo")
|
||||
.innerJoinAndSelect("photo.directory", "directory")
|
||||
.orderBy("photo.metadata.creationDate", "ASC");
|
||||
|
||||
|
||||
if (!searchType || searchType === SearchTypes.image) {
|
||||
query.orWhere('photo.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"});
|
||||
if (!searchType || searchType === SearchTypes.directory) {
|
||||
query.orWhere('directory.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"});
|
||||
}
|
||||
|
||||
if (!searchType || searchType === SearchTypes.image) {
|
||||
query.orWhere('photo.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"});
|
||||
}
|
||||
|
||||
if (!searchType || searchType === SearchTypes.position) {
|
||||
query.orWhere('photo.metadata.positionData LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"});
|
||||
}
|
||||
if (!searchType || searchType === SearchTypes.keyword) {
|
||||
query.orWhere('photo.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"});
|
||||
}
|
||||
let photos = await query
|
||||
.getMany();
|
||||
|
||||
|
||||
if (photos) {
|
||||
for (let i = 0; i < photos.length; i++) {
|
||||
photos[i].metadata.keywords = <any>JSON.parse(<any>photos[i].metadata.keywords);
|
||||
photos[i].metadata.cameraData = <any>JSON.parse(<any>photos[i].metadata.cameraData);
|
||||
photos[i].metadata.positionData = <any>JSON.parse(<any>photos[i].metadata.positionData);
|
||||
photos[i].metadata.size = <any>JSON.parse(<any>photos[i].metadata.size);
|
||||
}
|
||||
result.photos = photos;
|
||||
}
|
||||
|
||||
if (!searchType || searchType === SearchTypes.position) {
|
||||
query.orWhere('photo.metadata.positionData LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"});
|
||||
}
|
||||
if (!searchType || searchType === SearchTypes.keyword) {
|
||||
query.orWhere('photo.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"});
|
||||
}
|
||||
let photos = await query
|
||||
.innerJoinAndSelect("photo.directory", "directory")
|
||||
.getMany();
|
||||
result.directories = await connection
|
||||
.getRepository(DirectoryEntity)
|
||||
.createQueryBuilder("dir")
|
||||
.where('dir.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
|
||||
.getMany();
|
||||
|
||||
|
||||
if (photos) {
|
||||
for (let i = 0; i < photos.length; i++) {
|
||||
photos[i].metadata.keywords = <any>JSON.parse(<any>photos[i].metadata.keywords);
|
||||
photos[i].metadata.cameraData = <any>JSON.parse(<any>photos[i].metadata.cameraData);
|
||||
photos[i].metadata.positionData = <any>JSON.parse(<any>photos[i].metadata.positionData);
|
||||
photos[i].metadata.size = <any>JSON.parse(<any>photos[i].metadata.size);
|
||||
}
|
||||
result.photos = photos;
|
||||
}
|
||||
|
||||
result.directories = await connection
|
||||
.getRepository(DirectoryEntity)
|
||||
.createQueryBuilder("dir")
|
||||
.where('dir.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
|
||||
.getMany();
|
||||
|
||||
|
||||
return cb(null, result);
|
||||
}).catch((error) => {
|
||||
return cb(error, null);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
instantSearch(text: string, cb: (error: any, result: SearchResultDTO) => void) {
|
||||
MySQLConnection.getConnection().then(async connection => {
|
||||
async instantSearch(text: string) {
|
||||
const connection = await MySQLConnection.getConnection();
|
||||
|
||||
let result: SearchResultDTO = <SearchResultDTO>{
|
||||
searchText: text,
|
||||
directories: [],
|
||||
photos: []
|
||||
};
|
||||
let result: SearchResultDTO = <SearchResultDTO>{
|
||||
searchText: text,
|
||||
directories: [],
|
||||
photos: []
|
||||
};
|
||||
|
||||
let photos = await connection
|
||||
.getRepository(PhotoEntity)
|
||||
.createQueryBuilder("photo")
|
||||
.where('photo.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
|
||||
.orWhere('photo.metadata.positionData LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
|
||||
.orWhere('photo.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
|
||||
.innerJoinAndSelect("photo.directory", "directory")
|
||||
.setLimit(10)
|
||||
.getMany();
|
||||
let photos = await connection
|
||||
.getRepository(PhotoEntity)
|
||||
.createQueryBuilder("photo")
|
||||
.orderBy("photo.metadata.creationDate", "ASC")
|
||||
.where('photo.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
|
||||
.orWhere('photo.metadata.positionData LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
|
||||
.orWhere('photo.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
|
||||
.innerJoinAndSelect("photo.directory", "directory")
|
||||
.setLimit(10)
|
||||
.getMany();
|
||||
|
||||
|
||||
if (photos) {
|
||||
for (let i = 0; i < photos.length; i++) {
|
||||
photos[i].metadata.keywords = <any>JSON.parse(<any>photos[i].metadata.keywords);
|
||||
photos[i].metadata.cameraData = <any>JSON.parse(<any>photos[i].metadata.cameraData);
|
||||
photos[i].metadata.positionData = <any>JSON.parse(<any>photos[i].metadata.positionData);
|
||||
photos[i].metadata.size = <any>JSON.parse(<any>photos[i].metadata.size);
|
||||
}
|
||||
result.photos = photos;
|
||||
if (photos) {
|
||||
for (let i = 0; i < photos.length; i++) {
|
||||
photos[i].metadata.keywords = <any>JSON.parse(<any>photos[i].metadata.keywords);
|
||||
photos[i].metadata.cameraData = <any>JSON.parse(<any>photos[i].metadata.cameraData);
|
||||
photos[i].metadata.positionData = <any>JSON.parse(<any>photos[i].metadata.positionData);
|
||||
photos[i].metadata.size = <any>JSON.parse(<any>photos[i].metadata.size);
|
||||
}
|
||||
result.photos = photos;
|
||||
}
|
||||
|
||||
let directories = await connection
|
||||
.getRepository(DirectoryEntity)
|
||||
.createQueryBuilder("dir")
|
||||
.where('dir.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
|
||||
.setLimit(10)
|
||||
.getMany();
|
||||
let directories = await connection
|
||||
.getRepository(DirectoryEntity)
|
||||
.createQueryBuilder("dir")
|
||||
.where('dir.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
|
||||
.setLimit(10)
|
||||
.getMany();
|
||||
|
||||
result.directories = directories;
|
||||
result.directories = directories;
|
||||
|
||||
return cb(null, result);
|
||||
}).catch((error) => {
|
||||
return cb(error, null);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
private encapsulateAutoComplete(values: Array<string>, type: SearchTypes) {
|
||||
|
||||
Reference in New Issue
Block a user