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

179 lines
6.7 KiB
TypeScript
Raw Normal View History

2016-12-28 18:50:05 +08:00
import {AutoCompleteItem, SearchTypes} from "../../../common/entities/AutoCompleteItem";
import {ISearchManager} from "../interfaces/ISearchManager";
import {SearchResultDTO} from "../../../common/entities/SearchResultDTO";
import {SQLConnection} from "./SQLConnection";
2016-12-28 18:50:05 +08:00
import {PhotoEntity} from "./enitites/PhotoEntity";
import {DirectoryEntity} from "./enitites/DirectoryEntity";
2016-12-28 18:50:05 +08:00
export class SearchManager implements ISearchManager {
2018-01-31 09:01:16 +08:00
private static autoCompleteItemsUnique(array: Array<AutoCompleteItem>): Array<AutoCompleteItem> {
let a = array.concat();
for (let i = 0; i < a.length; ++i) {
for (let j = i + 1; j < a.length; ++j) {
if (a[i].equals(a[j]))
a.splice(j--, 1);
}
}
return a;
}
async autocomplete(text: string): Promise<Array<AutoCompleteItem>> {
2017-07-08 06:18:24 +08:00
const connection = await SQLConnection.getConnection();
2017-07-08 06:18:24 +08:00
let result: Array<AutoCompleteItem> = [];
let photoRepository = connection.getRepository(PhotoEntity);
let directoryRepository = connection.getRepository(DirectoryEntity);
(await photoRepository
.createQueryBuilder('photo')
2018-01-31 09:01:16 +08:00
.select('DISTINCT(photo.metadata.keywords)')
2017-07-08 06:18:24 +08:00
.where('photo.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
2017-10-20 00:08:07 +08:00
.limit(5)
2017-07-08 06:18:24 +08:00
.getRawMany())
2018-01-31 09:01:16 +08:00
.map(r => <Array<string>>r.metadataKeywords.split(","))
2017-07-08 06:18:24 +08:00
.forEach(keywords => {
result = result.concat(this.encapsulateAutoComplete(keywords.filter(k => k.toLowerCase().indexOf(text.toLowerCase()) != -1), SearchTypes.keyword));
});
(await photoRepository
.createQueryBuilder('photo')
2018-01-31 09:01:16 +08:00
.select('photo.metadata.positionData.country as country, photo.metadata.positionData.state as state, photo.metadata.positionData.city as city')
.where('photo.metadata.positionData.country LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
.orWhere('photo.metadata.positionData.state LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
.orWhere('photo.metadata.positionData.city LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
.groupBy('photo.metadata.positionData.country, photo.metadata.positionData.state, photo.metadata.positionData.city')
2017-10-20 00:08:07 +08:00
.limit(5)
2017-07-08 06:18:24 +08:00
.getRawMany())
.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 + "%"})
2017-10-20 00:08:07 +08:00
.limit(5)
2017-07-08 06:18:24 +08:00
.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 + "%"})
2017-10-20 00:08:07 +08:00
.limit(5)
2017-07-08 06:18:24 +08:00
.getRawMany())
.map(r => r.name), SearchTypes.directory));
2018-01-31 09:01:16 +08:00
return SearchManager.autoCompleteItemsUnique(result);
2017-07-08 04:54:18 +08:00
}
2018-01-31 09:01:16 +08:00
async search(text: string, searchType: SearchTypes): Promise<SearchResultDTO> {
const connection = await SQLConnection.getConnection();
2017-07-08 04:54:18 +08:00
2018-01-31 09:01:16 +08:00
const result: SearchResultDTO = <SearchResultDTO>{
2017-07-08 06:18:24 +08:00
searchText: text,
searchType: searchType,
directories: [],
2017-07-26 03:36:28 +08:00
photos: [],
resultOverflow: false
2017-07-08 06:18:24 +08:00
};
2017-07-08 04:54:18 +08:00
2017-07-08 06:18:24 +08:00
let query = connection
.getRepository(PhotoEntity)
.createQueryBuilder("photo")
.innerJoinAndSelect("photo.directory", "directory")
.orderBy("photo.metadata.creationDate", "ASC");
2017-07-08 04:54:18 +08:00
2017-07-08 06:18:24 +08:00
if (!searchType || searchType === SearchTypes.directory) {
query.orWhere('directory.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"});
}
2017-07-08 04:54:18 +08:00
2017-07-08 06:18:24 +08:00
if (!searchType || searchType === SearchTypes.image) {
query.orWhere('photo.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"});
}
if (!searchType || searchType === SearchTypes.position) {
2018-01-31 09:01:16 +08:00
query.orWhere('photo.metadata.positionData.country LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
.orWhere('photo.metadata.positionData.state LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
.orWhere('photo.metadata.positionData.city LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"});
2017-07-08 06:18:24 +08:00
}
if (!searchType || searchType === SearchTypes.keyword) {
query.orWhere('photo.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"});
}
2018-01-31 09:01:16 +08:00
result.photos = await query
2017-10-20 00:08:07 +08:00
.limit(2001)
2017-07-08 06:18:24 +08:00
.getMany();
2018-01-31 09:01:16 +08:00
if (result.photos.length > 2000) {
result.resultOverflow = true;
2017-07-08 06:18:24 +08:00
}
2017-07-08 04:54:18 +08:00
2017-07-08 06:18:24 +08:00
result.directories = await connection
.getRepository(DirectoryEntity)
.createQueryBuilder("dir")
.where('dir.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
2017-10-20 00:08:07 +08:00
.limit(201)
2017-07-08 06:18:24 +08:00
.getMany();
2017-07-08 04:54:18 +08:00
2017-07-26 03:36:28 +08:00
if (result.directories.length > 200) {
result.resultOverflow = true;
}
2017-07-08 04:54:18 +08:00
2017-07-08 06:18:24 +08:00
return result;
2017-07-08 04:54:18 +08:00
}
2018-01-31 09:01:16 +08:00
async instantSearch(text: string): Promise<SearchResultDTO> {
const connection = await SQLConnection.getConnection();
2017-07-08 06:18:24 +08:00
let result: SearchResultDTO = <SearchResultDTO>{
searchText: text,
2018-01-31 09:01:16 +08:00
//searchType:undefined, not adding this
2017-07-08 06:18:24 +08:00
directories: [],
2017-07-26 03:36:28 +08:00
photos: [],
resultOverflow: false
2017-07-08 06:18:24 +08:00
};
2018-01-31 09:01:16 +08:00
result.photos = await connection
2017-07-08 06:18:24 +08:00
.getRepository(PhotoEntity)
.createQueryBuilder("photo")
.orderBy("photo.metadata.creationDate", "ASC")
.where('photo.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
2018-01-31 09:01:16 +08:00
.orWhere('photo.metadata.positionData.country LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
.orWhere('photo.metadata.positionData.state LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
.orWhere('photo.metadata.positionData.city LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
2017-07-08 06:18:24 +08:00
.orWhere('photo.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
.innerJoinAndSelect("photo.directory", "directory")
2017-10-20 00:08:07 +08:00
.limit(10)
2017-07-08 06:18:24 +08:00
.getMany();
2018-01-31 09:01:16 +08:00
result.directories = await connection
2017-07-08 06:18:24 +08:00
.getRepository(DirectoryEntity)
.createQueryBuilder("dir")
.where('dir.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"})
2017-10-20 00:08:07 +08:00
.limit(10)
2017-07-08 06:18:24 +08:00
.getMany();
2017-07-08 04:54:18 +08:00
2017-07-08 06:18:24 +08:00
return result;
2017-07-08 04:54:18 +08:00
}
2018-01-31 09:01:16 +08:00
private encapsulateAutoComplete(values: Array<string>, type: SearchTypes): Array<AutoCompleteItem> {
2017-07-08 04:54:18 +08:00
let res = [];
values.forEach((value) => {
res.push(new AutoCompleteItem(value, type));
});
return res;
}
}