Refactored matching to simplify.

master
Sander Vocke 6 years ago
parent 0f4b465db5
commit 5d0d2965f4
  1. 135
      src/queries.js

@ -61,15 +61,13 @@ export function do_tag_query(query, database) {
} }
export const MatchTypeEnum = { export const MatchTypeEnum = {
MATCH_EQUALS: 1, MATCH_IMAGE_NAME_EQUALS: 1,
MATCH_NATURAL: 2, MATCH_IMAGE_NAME_NATURAL: 2,
}; MATCH_ALBUM_EQUALS: 3, // Match on the full name (relative path) of the relevant album, if any
MATCH_ALBUM_EQUALS_OR_CHILD: 4, // Match on the full name (relative path) of the relevant album, if any, or any of its children
export const MatchAgainstEnum = { MATCH_ALBUM_NATURAL: 5,
MATCH_IMAGE_NAME: 1, // Match on the name of the relevant image(s), if any MATCH_ALBUM_NAME_EQUALS: 6, // Match on the local album name (excluding parents)
MATCH_ALBUM_NAME: 2, // Match on the name of the relevant album(s), if any MATCH_TAG_EQUALS: 7, // Match on the name of the relevant tag(s), if any
MATCH_ALBUM_NAME_IN_TREE: 3, // Match on any album name in the album tree branch, including parents
MATCH_TAG_NAME: 4, // Match on the name of the relevant tag(s), if any
} }
export const ResultTypeEnum = { export const ResultTypeEnum = {
@ -116,10 +114,10 @@ export class NegationFilter extends ResultFilter {
simplify() { simplify() {
var f = this.body.simplify(); var f = this.body.simplify();
if(f.is_true()) { if (f.is_true()) {
return new ConstFilter(this.result_type, false); return new ConstFilter(this.result_type, false);
} }
if(f.is_false()) { if (f.is_false()) {
return new ConstFilter(this.result_type, true); return new ConstFilter(this.result_type, true);
} }
return this; return this;
@ -127,52 +125,39 @@ export class NegationFilter extends ResultFilter {
} }
export class MatchingFilter extends ResultFilter { export class MatchingFilter extends ResultFilter {
constructor(rtype, against, from, mtype) { constructor(rtype, from, mtype) {
super(rtype); super(rtype);
this.match_against = against;
this.match_from = from; this.match_from = from;
this.match_type = mtype; this.match_type = mtype;
} }
// What string to match against.
match_against = MatchAgainstEnum.MATCH_IMAGE_NAME;
// optional string used in the filtering // optional string used in the filtering
match_from = ""; match_from = "";
// How to use the matching string // What and how to match
match_type = MatchTypeEnum.MATCH_EQUALS; match_type = MatchTypeEnum.MATCH_IMAGE_NAME_EQUALS;
to_sql_where() { to_sql_where() {
var expr; if (this.match_type == MatchTypeEnum.MATCH_IMAGE_NAME_EQUALS) {
if(this.match_against === MatchAgainstEnum.MATCH_IMAGE_NAME) { return '(Images.name="' + this.match_from + '")';
if(this.match_type === MatchTypeEnum.MATCH_EQUALS) { } else if (this.match_type == MatchTypeEnum.MATCH_IMAGE_NAME_NATURAL) {
return '(Images.name="' + this.match_from + '")'; return '(LOWER(Images.name) REGEXP LOWER(".*'
} else if(this.match_type === MatchTypeEnum.MATCH_NATURAL) { + escape_regex(this.match_from)
expr = '".*' + escape_regex(this.match_from) + '.*"'; + ')).*"';
return "(LOWER(Images.name) REGEXP LOWER(" + expr +"))"; } else if (this.match_type == MatchTypeEnum.MATCH_ALBUM_EQUALS) {
} return '(Albums.relativePath = "' + this.match_from + '")';
} else if(this.match_against === MatchAgainstEnum.MATCH_TAG_NAME) { } else if (this.match_type == MatchTypeEnum.MATCH_ALBUM_EQUALS_OR_CHILD) {
if(this.match_type === MatchTypeEnum.MATCH_EQUALS) { return '(Albums.relativePath REGEXP "'
return '(Tags.name="' + this.match_from + '")'; + escape_regex(this.match_from)
} else if(this.match_type === MatchTypeEnum.MATCH_NATURAL) { + '(\/[^\/]+)*")';
expr = '".*' + escape_regex(this.match_from) + '.*"'; } else if (this.match_type == MatchTypeEnum.MATCH_ALBUM_NATURAL) {
return '(LOWER(Tags.name) REGEXP LOWER("' + expr + '"))'; throw new Error("Natural matching on album names is not yet supported.");
} } else if (this.match_type == MatchTypeEnum.MATCH_ALBUM_NAME_EQUALS) {
} else if(this.match_against === MatchAgainstEnum.MATCH_ALBUM_NAME) { return '(Albums.relativePath REGEXP "\/(.*\/)*'
if(this.match_type === MatchTypeEnum.MATCH_EQUALS) { + escape_regex(this.match_from)
expr = '\/(.*\/)*' + escape_regex(this.match_from); + '(\/[^\/]+)*")';
return '(Albums.relativePath REGEXP "' + expr + '")'; } else if (this.match_type == MatchTypeEnum.MATCH_TAG_EQUALS) {
} else if(this.match_type === MatchTypeEnum.MATCH_NATURAL) { return '(Tags.name="' + this.match_from + '")';
throw new Error("Natural matching on album names is not yet supported.");
}
} else if(this.match_against === MatchAgainstEnum.MATCH_ALBUM_NAME_IN_TREE) {
if(this.match_type === MatchTypeEnum.MATCH_EQUALS) {
expr = escape_regex(this.match_from) + '(\/[^\/]+)*';
return '(Albums.relativePath REGEXP "' + expr + '")';
} else if(this.match_type === MatchTypeEnum.MATCH_NATURAL) {
throw new Error("Natural matching on album tree names is not yet supported.");
}
} }
console.log(this); console.log(this);
@ -210,20 +195,20 @@ export class LogicalOperatorFilter extends ResultFilter {
var a = this.sub_filter_a.simplify(); var a = this.sub_filter_a.simplify();
var b = this.sub_filter_b.simplify(); var b = this.sub_filter_b.simplify();
if(this.operator === LogicalOperatorEnum.OR) { if (this.operator === LogicalOperatorEnum.OR) {
if(a.is_true() || b.is_true()) { if (a.is_true() || b.is_true()) {
return new ConstFilter(this.return_type, true); return new ConstFilter(this.return_type, true);
} }
if(a.is_false()) { return b; } if (a.is_false()) { return b; }
if(b.is_false()) { return a; } if (b.is_false()) { return a; }
} }
if(this.operator === LogicalOperatorEnum.AND) { if (this.operator === LogicalOperatorEnum.AND) {
if(a.is_false() || b.is_false()) { if (a.is_false() || b.is_false()) {
return new ConstFilter(this.return_type, false); return new ConstFilter(this.return_type, false);
} }
if(a.is_true()) { return b; } if (a.is_true()) { return b; }
if(b.is_true()) { return a; } if (b.is_true()) { return a; }
} }
return this; return this;
@ -278,7 +263,7 @@ export function maybe_tag_query(user_query) {
} }
export function filter_is_const_false(filter) { export function filter_is_const_false(filter) {
if(filter instanceof ConstFilter && filter.constval === false) { if (filter instanceof ConstFilter && filter.constval === false) {
return true; return true;
} }
// TODO resolve recursively // TODO resolve recursively
@ -293,45 +278,41 @@ function filter_from_text_segment(result_type, segment) {
// Option 1: match on image name // Option 1: match on image name
name_filter = new MatchingFilter( name_filter = new MatchingFilter(
result_type, result_type,
MatchAgainstEnum.MATCH_IMAGE_NAME,
segment['text'], segment['text'],
MatchTypeEnum.MATCH_NATURAL MatchTypeEnum.MATCH_IMAGE_NAME_NATURAL
); );
// Option 2: match on album path // Option 2: match on album path (TODO: need natural matching)
var album_filter = new MatchingFilter( var album_filter = new MatchingFilter(
result_type, result_type,
MatchAgainstEnum.MATCH_ALBUM_NAME,
segment['text'], segment['text'],
MatchTypeEnum.MATCH_EQUALS MatchTypeEnum.MATCH_ALBUM_NAME_EQUALS
); );
filter = new LogicalOperatorFilter(result_type, name_filter, album_filter, LogicalOperatorEnum.OR); filter = new LogicalOperatorFilter(result_type, name_filter, album_filter, LogicalOperatorEnum.OR);
if(segment['negated']) { if (segment['negated']) {
filter = new NegationFilter(result_type, filter); filter = new NegationFilter(result_type, filter);
} }
} else if (result_type === ResultTypeEnum.ALBUM) { } else if (result_type === ResultTypeEnum.ALBUM) {
// TODO: We need a natural matcher for album names // TODO: We need a natural matcher for album names
name_filter = new MatchingFilter( name_filter = new MatchingFilter(
result_type, result_type,
MatchAgainstEnum.MATCH_ALBUM_NAME,
segment['text'], segment['text'],
MatchTypeEnum.MATCH_EQUALS MatchTypeEnum.MATCH_ALBUM_NAME_EQUALS
); );
filter = name_filter; filter = name_filter;
if(segment['negated']) { if (segment['negated']) {
filter = new NegationFilter(result_type, filter); filter = new NegationFilter(result_type, filter);
} }
} else if (result_type === ResultTypeEnum.TAG) { } else if (result_type === ResultTypeEnum.TAG) {
// Match against the tag name. // Match against the tag name.
name_filter = new MatchingFilter( name_filter = new MatchingFilter(
result_type, result_type,
MatchAgainstEnum.MATCH_TAG_NAME,
segment['text'], segment['text'],
MatchTypeEnum.MATCH_EQUALS MatchTypeEnum.MATCH_TAG_NAME_EQUALS
); );
filter = name_filter; filter = name_filter;
if(segment['negated']) { if (segment['negated']) {
filter = new NegationFilter(result_type, filter); filter = new NegationFilter(result_type, filter);
} }
} }
@ -362,10 +343,11 @@ export function user_query_from_search_string(search_string) {
export function user_query_from_browsed_album(album_path) { export function user_query_from_browsed_album(album_path) {
var r = new UserQuery(); var r = new UserQuery();
var match_type = MatchTypeEnum.MATCH_EQUALS; r.image_filter = new MatchingFilter(
var match_against = MatchAgainstEnum.MATCH_ALBUM_NAME_IN_TREE; ResultTypeEnum.IMAGE,
var match_text = album_path; album_path,
r.image_filter = new MatchingFilter(ResultTypeEnum.IMAGE, match_against, match_text, match_type, false).simplify(); MatchTypeEnum.MATCH_ALBUM_EQUALS_OR_CHILD,
false).simplify();
r.album_filter = new ConstFilter(ResultTypeEnum.ALBUM, false).simplify(); r.album_filter = new ConstFilter(ResultTypeEnum.ALBUM, false).simplify();
return r; return r;
@ -373,10 +355,11 @@ export function user_query_from_browsed_album(album_path) {
export function user_query_from_browsed_tag(name) { export function user_query_from_browsed_tag(name) {
var r = new UserQuery(); var r = new UserQuery();
var match_type = MatchTypeEnum.MATCH_EQUALS; r.image_filter = new MatchingFilter(
var match_text = name; ResultTypeEnum.IMAGE,
var match_against = MatchAgainstEnum.MATCH_TAG_NAME; name,
r.image_filter = new MatchingFilter(ResultTypeEnum.IMAGE, match_against, match_text, match_type, false).simplify(); MatchTypeEnum.MATCH_TAG_EQUALS,
false).simplify();
r.album_filter = new ConstFilter(ResultTypeEnum.ALBUM, false).simplify(); r.album_filter = new ConstFilter(ResultTypeEnum.ALBUM, false).simplify();
r.tag_filter = new ConstFilter(ResultTypeEnum.TAG, false).simplify(); r.tag_filter = new ConstFilter(ResultTypeEnum.TAG, false).simplify();

Loading…
Cancel
Save