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

182 lines
6.6 KiB
TypeScript
Raw Normal View History

2016-05-16 17:03:11 +08:00
import {AutoCompleteItem, SearchTypes} from "../../../common/entities/AutoCompleteItem";
2016-05-05 00:34:54 +08:00
import {ISearchManager} from "../ISearchManager";
import {DirectoryModel} from "./entities/DirectoryModel";
import {PhotoModel} from "./entities/PhotoModel";
2016-05-10 03:43:52 +08:00
import {SearchResult} from "../../../common/entities/SearchResult";
2016-05-05 00:34:54 +08:00
2016-05-09 23:04:56 +08:00
export class MongoSearchManager implements ISearchManager {
2016-05-05 00:34:54 +08:00
2016-05-09 23:04:56 +08:00
constructor() {
2016-05-05 00:34:54 +08:00
}
2016-05-09 23:04:56 +08:00
autocomplete(text, cb:(error:any, result:Array<AutoCompleteItem>) => void) {
2016-05-05 00:34:54 +08:00
console.log("autocomplete: " + text);
let items:Array<AutoCompleteItem> = [];
let promises = [];
promises.push(
PhotoModel.find({name: {$regex: text, $options: "i"}})
.limit(10).select('name').exec().then((res:Array<any>)=> {
2016-05-16 17:03:11 +08:00
items = items.concat(this.encapsulateAutoComplete(res.map(r => r.name), SearchTypes.image));
}));
promises.push(
PhotoModel.find({"metadata.positionData.city": {$regex: text, $options: "i"}})
.limit(10).select('metadata.positionData.city').exec().then((res:Array<any>)=> {
2016-05-16 17:03:11 +08:00
items = items.concat(this.encapsulateAutoComplete(res.map(r => r.metadata.positionData.city), SearchTypes.position));
}));
promises.push(
PhotoModel.find({"metadata.positionData.state": {$regex: text, $options: "i"}})
.limit(10).select('metadata.positionData.state').exec().then((res:Array<any>)=> {
2016-05-16 17:03:11 +08:00
items = items.concat(this.encapsulateAutoComplete(res.map(r => r.metadata.positionData.state), SearchTypes.position));
}));
promises.push(
PhotoModel.find({"metadata.positionData.country": {$regex: text, $options: "i"}})
.limit(10).select('metadata.positionData.country').exec().then((res:Array<any>)=> {
2016-05-16 17:03:11 +08:00
items = items.concat(this.encapsulateAutoComplete(res.map(r => r.metadata.positionData.country), SearchTypes.position));
}));
//TODO: fix caseinsensitivity
promises.push(
PhotoModel.find({"metadata.keywords": {$regex: text, $options: "i"}})
.limit(10).select('metadata.keywords').exec().then((res:Array<any>)=> {
res.forEach((photo)=> {
2016-05-16 17:03:11 +08:00
items = items.concat(this.encapsulateAutoComplete(photo.metadata.keywords.filter(k => k.indexOf(text) != -1), SearchTypes.keyword));
});
}));
promises.push(
2016-05-09 23:04:56 +08:00
DirectoryModel.find({
name: {$regex: text, $options: "i"}
}).limit(10).select('name').exec().then((res:Array<any>)=> {
2016-05-16 17:03:11 +08:00
items = items.concat(this.encapsulateAutoComplete(res.map(r => r.name), SearchTypes.directory));
}));
2016-05-05 00:34:54 +08:00
Promise.all(promises).then(()=> {
return cb(null, this.autoCompleteItemsUnique(items));
}).catch((err)=> {
console.error(err);
return cb(err, null);
2016-05-05 00:34:54 +08:00
});
2016-05-05 00:34:54 +08:00
}
2016-05-16 17:03:11 +08:00
search(text:string, searchType:SearchTypes, cb:(error:any, result:SearchResult) => void) {
console.log("search: " + text + ", type:" + searchType);
2016-05-10 03:43:52 +08:00
let result:SearchResult = new SearchResult();
2016-05-16 17:03:11 +08:00
let promises = [];
let photoFilterOR = [];
2016-05-10 03:43:52 +08:00
result.searchText = text;
2016-05-16 17:03:11 +08:00
result.searchType = searchType;
2016-05-10 03:43:52 +08:00
2016-05-16 17:03:11 +08:00
if (!searchType || searchType === SearchTypes.image) {
photoFilterOR.push({name: {$regex: text, $options: "i"}});
}
if (!searchType || searchType === SearchTypes.position) {
photoFilterOR.push({"metadata.positionData.city": {$regex: text, $options: "i"}});
photoFilterOR.push({"metadata.positionData.state": {$regex: text, $options: "i"}});
photoFilterOR.push({"metadata.positionData.country": {$regex: text, $options: "i"}});
}
if (!searchType || searchType === SearchTypes.keyword) {
photoFilterOR.push({"metadata.keywords": {$regex: text, $options: "i"}});
}
let photoFilter = {};
if (photoFilterOR.length == 1) {
photoFilter = photoFilterOR[0];
} else {
photoFilter = {$or: photoFilterOR};
}
if (!searchType || photoFilterOR.length > 0) {
promises.push(PhotoModel.find(photoFilter).populate('directory', 'name path').exec().then((res:Array<any>) => {
result.photos = res;
}));
}
if (!searchType || searchType === SearchTypes.directory) {
promises.push(DirectoryModel.find({
2016-05-10 03:43:52 +08:00
name: {
$regex: text,
$options: "i"
}
2016-05-16 17:03:11 +08:00
}).exec().then((res:Array<any>) => {
2016-05-10 03:43:52 +08:00
result.directories = res;
2016-05-16 17:03:11 +08:00
}));
}
2016-05-10 03:43:52 +08:00
2016-05-16 17:03:11 +08:00
Promise.all(promises).then(()=> {
return cb(null, result);
}).catch((err)=> {
console.error(err);
return cb(err, null);
2016-05-10 03:43:52 +08:00
});
}
instantSearch(text, cb:(error:any, result:SearchResult) => void) {
console.log("instantSearch: " + text);
let result:SearchResult = new SearchResult();
result.searchText = text;
PhotoModel.find({
$or: [
{name: {$regex: text, $options: "i"}},
{"metadata.positionData.city": {$regex: text, $options: "i"}},
{"metadata.positionData.state": {$regex: text, $options: "i"}},
{"metadata.positionData.country": {$regex: text, $options: "i"}},
{"metadata.keywords": {$regex: text, $options: "i"}}
]
2016-05-10 03:43:52 +08:00
}).limit(10).populate('directory', 'name path').exec((err, res:Array<any>) => {
if (err || !res) {
return cb(err, null);
}
result.photos = res;
DirectoryModel.find({
name: {
$regex: text,
$options: "i"
}
}).limit(10).exec((err, res:Array<any>) => {
if (err || !res) {
return cb(err, null);
}
result.directories = res;
return cb(null, result);
});
});
}
2016-05-16 17:03:11 +08:00
private encapsulateAutoComplete(values:Array<string>, type:SearchTypes) {
2016-05-05 00:34:54 +08:00
let res = [];
2016-05-09 23:04:56 +08:00
values.forEach((value)=> {
res.push(new AutoCompleteItem(value, type));
2016-05-05 00:34:54 +08:00
});
return res;
}
private autoCompleteItemsUnique(array:Array<AutoCompleteItem>) {
var a = array.concat();
for (var i = 0; i < a.length; ++i) {
for (var j = i + 1; j < a.length; ++j) {
if (a[i].equals(a[j]))
a.splice(j--, 1);
}
}
return a;
}
2016-05-05 00:34:54 +08:00
}