|
|
|
@ -24,54 +24,118 @@ export const MatchTypeEnum = { |
|
|
|
|
MATCH_LIKE: 2, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
export const ResultFilterTypeEnum = { |
|
|
|
|
MATCH_NAME: 1, |
|
|
|
|
export const MatchAgainstEnum = { |
|
|
|
|
MATCH_RESULT_NAME: 1, // Match on the name of whatever object type we are querying for
|
|
|
|
|
MATCH_IMAGE_NAME: 2, // Match on the name of the relevant image, if any
|
|
|
|
|
MATCH_ALBUM_NAME: 3, // Match on the name of the relevant album, if any
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export const ResultTypeEnum = { |
|
|
|
|
IMAGE: 1, |
|
|
|
|
ALBUM: 2, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export class ResultFilter { |
|
|
|
|
constructor(type) { this.result_type = type; } |
|
|
|
|
|
|
|
|
|
result_type = ResultTypeEnum.IMAGE; |
|
|
|
|
|
|
|
|
|
to_sql_where() { return "(1=1)"; } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export class ConstFilter extends ResultFilter { |
|
|
|
|
constructor(type, val) { super(type); this.constval = val; } |
|
|
|
|
constval = true; // True lets everything through, false rejects everything
|
|
|
|
|
|
|
|
|
|
to_sql_where() { |
|
|
|
|
return this.constval ? "(1=1)" : "(1=0)"; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function match_column_name(result_type, match_against) { |
|
|
|
|
if(match_against == MatchAgainstEnum.MATCH_IMAGE_NAME) { |
|
|
|
|
return "Image.name"; |
|
|
|
|
} |
|
|
|
|
if(match_against == MatchAgainstEnum.MATCH_ALBUM_NAME) { |
|
|
|
|
return "Album.name"; |
|
|
|
|
} |
|
|
|
|
if(match_against == MatchAgainstEnum.MATCH_RESULT_NAME) { |
|
|
|
|
if(result_type == ResultTypeEnum.IMAGE) { |
|
|
|
|
return match_column_name(result_type, MatchAgainstEnum.MATCH_IMAGE_NAME); |
|
|
|
|
} |
|
|
|
|
if(result_type == ResultTypeEnum.ALBUM) { |
|
|
|
|
return match_column_name(result_type, MatchAgainstEnum.MATCH_ALBUM_NAME); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
throw new Error("Could not get column name for matching properties passed."); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export class MatchingFilter extends ResultFilter { |
|
|
|
|
constructor(rtype, against, from, mtype, negate) { |
|
|
|
|
super(rtype); |
|
|
|
|
this.match_against = against; |
|
|
|
|
this.match_from = from; |
|
|
|
|
this.match_type = mtype; |
|
|
|
|
this.negate = negate; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// What kind of filtering to apply
|
|
|
|
|
type = ResultFilterTypeEnum.MATCH_NAME; |
|
|
|
|
match_against = MatchAgainstEnum.MATCH_RESULT_NAME; |
|
|
|
|
|
|
|
|
|
// optional string used in the filtering
|
|
|
|
|
match_against = ""; |
|
|
|
|
match_from = ""; |
|
|
|
|
|
|
|
|
|
// How to use the matching string
|
|
|
|
|
match_type = MatchTypeEnum.MATCH_EQUALS; |
|
|
|
|
|
|
|
|
|
// On which types of results to apply the filter
|
|
|
|
|
result_types = []; |
|
|
|
|
|
|
|
|
|
// If true, negates the filter
|
|
|
|
|
negate = false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export class UserQuery { |
|
|
|
|
result_filters = []; |
|
|
|
|
include_result_types = [ ResultTypeEnum.IMAGE ]; |
|
|
|
|
to_sql_where() { |
|
|
|
|
var match_against_str = match_column_name(this.result_type, this.match_against); |
|
|
|
|
var match_type_str = false; |
|
|
|
|
|
|
|
|
|
if(this.match_type == MatchTypeEnum.MATCH_EQUALS) { |
|
|
|
|
match_type_str = "="; |
|
|
|
|
} else if(this.match_type == MatchTypeEnum.MATCH_LIKE) { |
|
|
|
|
match_type_str = " LIKE "; |
|
|
|
|
} else { |
|
|
|
|
throw new Error('Unsupported match type: ' + this.match_type); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return "(" + (this.negate ? "NOT " : "") + match_against_str + "\"" + match_type_str + "\"" + this.match_from + ")"; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export function image_filter_to_where(image_filter) { |
|
|
|
|
var match_from = false; |
|
|
|
|
var match_to = image_filter.match_against; |
|
|
|
|
var match_operator = false; |
|
|
|
|
export const LogicalOperatorEnum = { |
|
|
|
|
AND: 1, |
|
|
|
|
OR: 2, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(image_filter.type == ResultFilterTypeEnum.MATCH_NAME) { |
|
|
|
|
match_from = "Image.name"; |
|
|
|
|
export class LogicalOperatorFilter extends ResultFilter { |
|
|
|
|
constructor(type, a, b, op) { super(type); this.sub_filter_a = a; this.sub_filter_b = b; this.operator = op; } |
|
|
|
|
sub_filter_a = false; |
|
|
|
|
sub_filter_b = false; |
|
|
|
|
operator = LogicalOperatorEnum.AND; |
|
|
|
|
|
|
|
|
|
to_sql_where() { |
|
|
|
|
var where1 = this.sub_filter_a.to_sql_where(); |
|
|
|
|
var where2 = this.sub_filter_b.to_sql_where(); |
|
|
|
|
var operator_str = ""; |
|
|
|
|
if(this.operator == LogicalOperatorEnum.AND) { |
|
|
|
|
operator_str = " AND "; |
|
|
|
|
} else if(this.operator == LogicalOperatorEnum.OR) { |
|
|
|
|
operator_str = " OR "; |
|
|
|
|
} else { |
|
|
|
|
throw new Error("Unsupported image filter type: " + image_filter.type); |
|
|
|
|
throw new Error('Unsupported logical operator: ' + this.operator); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(image_filter.match_type == MatchTypeEnum.MATCH_EQUALS) { |
|
|
|
|
match_operator = "="; |
|
|
|
|
} else if(image_filter.match_type == MatchTypeEnum.MATCH_LIKE) { |
|
|
|
|
match_operator = " LIKE "; |
|
|
|
|
return "(" + where1 + operator_str + where2 + ")"; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return match_from + match_operator + match_to; |
|
|
|
|
export class UserQuery { |
|
|
|
|
image_filter = new ConstFilter(ResultTypeEnum.IMAGE, true); |
|
|
|
|
album_filter = new ConstFilter(ResultTypeEnum.ALBUM, true); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// This query will return database entries with the fields "id", "uniqueHash", "relativePath" (of the album) and "name" for each matching image.
|
|
|
|
@ -80,32 +144,16 @@ export function image_query_with_where(maybe_where) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export function maybe_image_query(user_query) { |
|
|
|
|
if(!user_query.include_result_types.includes(ResultTypeEnum.IMAGE)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
var where = false; |
|
|
|
|
if(user_query.image_filters.length) { |
|
|
|
|
where = "WHERE "; |
|
|
|
|
var i = 0; |
|
|
|
|
user_query.image_filters.forEach(elem => { |
|
|
|
|
if(i > 0) { |
|
|
|
|
where += "AND"; |
|
|
|
|
} |
|
|
|
|
where += image_filter_to_where(elem) + " "; |
|
|
|
|
i++; |
|
|
|
|
}); |
|
|
|
|
if(user_query.image_filter) { |
|
|
|
|
where = "WHERE " + user_query.image_filter.to_sql_where(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return image_query_with_where(where); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function filter_from_text_segment(segment) { |
|
|
|
|
var r = new ResultFilter(); |
|
|
|
|
r.match_against = segment['text']; |
|
|
|
|
r.negate = segment['negated']; |
|
|
|
|
r.match_type = MatchTypeEnum.MATCH_EQUALS; |
|
|
|
|
r.type = ResultFilterTypeEnum.MATCH_NAME; |
|
|
|
|
return r; |
|
|
|
|
function filter_from_text_segment(result_type, segment) { |
|
|
|
|
return new MatchingFilter(result_type, MatchAgainstEnum.MATCH_RESULT_NAME, |
|
|
|
|
segment['text'], MatchTypeEnum.MATCH_EQUALS, segment['negated']); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export function user_query_from_search_string(search_string) { |
|
|
|
@ -118,9 +166,14 @@ export function user_query_from_search_string(search_string) { |
|
|
|
|
var r = new UserQuery(); |
|
|
|
|
|
|
|
|
|
texts.forEach(text => { |
|
|
|
|
r.result_filters.push(filter_from_text_segment(text)); |
|
|
|
|
console.log(text); |
|
|
|
|
r.image_filter = new LogicalOperatorFilter(ResultTypeEnum.IMAGE, r.image_filter, |
|
|
|
|
filter_from_text_segment(ResultTypeEnum.IMAGE, text), LogicalOperatorEnum.AND); |
|
|
|
|
r.album_filter = new LogicalOperatorFilter(ResultTypeEnum.ALBUM, r.album_filter, |
|
|
|
|
filter_from_text_segment(ResultTypeEnum.ALBUM, text), LogicalOperatorEnum.AND); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
console.log(search_string); |
|
|
|
|
console.log(r); |
|
|
|
|
console.log(maybe_image_query(r)); |
|
|
|
|
} |