-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LIKE, IN, BETWEEN operators -- filter extension #178
Changes from 4 commits
95d2f27
c8edf52
3f1a3e5
8ed4d35
73f6dc4
7bf41c6
e7330dc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,9 @@ | |
Basic CQL2 (AND, OR, NOT), comparison operators (=, <>, <, <=, >, >=), and IS NULL. | ||
The comparison operators are allowed against string, numeric, boolean, date, and datetime types. | ||
|
||
Advanced CQL2 LIKE comparison operator (http://www.opengis.net/spec/cql2/1.0/req/advanced-comparison-operators). | ||
The LIKE comparison operator is allowed against string types. | ||
|
||
Basic Spatial Operators (http://www.opengis.net/spec/cql2/1.0/conf/basic-spatial-operators) | ||
defines the intersects operator (S_INTERSECTS). | ||
""" | ||
|
@@ -78,6 +81,15 @@ def to_es(self): | |
) | ||
|
||
|
||
class AdvancedComparisonOp(str, Enum): | ||
"""Advanced Comparison operator. | ||
|
||
CQL2 advanced comparison operator like (~). | ||
""" | ||
|
||
like = "like" | ||
|
||
|
||
class SpatialIntersectsOp(str, Enum): | ||
"""Spatial intersections operator s_intersects.""" | ||
|
||
|
@@ -152,7 +164,7 @@ def validate(cls, v): | |
class Clause(BaseModel): | ||
"""Filter extension clause.""" | ||
|
||
op: Union[LogicalOp, ComparisonOp, SpatialIntersectsOp] | ||
op: Union[LogicalOp, ComparisonOp, AdvancedComparisonOp, SpatialIntersectsOp] | ||
args: List[Arg] | ||
|
||
def to_es(self): | ||
|
@@ -171,6 +183,16 @@ def to_es(self): | |
"must_not": [{"term": {to_es(self.args[0]): to_es(self.args[1])}}] | ||
} | ||
} | ||
elif self.op == AdvancedComparisonOp.like: | ||
return { | ||
"wildcard": { | ||
to_es(self.args[0]): { | ||
"value": cql2_like_to_es(str(to_es(self.args[1]))), | ||
"boost": 1.0, | ||
jamesfisher-geo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"case_insensitive": "true", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should be case sensitive There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you mean that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, since AFAIK LIKE is a case sensitive operation (e.g., There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Got it. Updated in e7330dc |
||
} | ||
} | ||
} | ||
elif ( | ||
self.op == ComparisonOp.lt | ||
or self.op == ComparisonOp.lte | ||
|
@@ -210,3 +232,22 @@ def to_es(arg: Arg): | |
return arg | ||
else: | ||
raise RuntimeError(f"unknown arg {repr(arg)}") | ||
|
||
|
||
def cql2_like_to_es(input_string): | ||
"""Convert arugument in CQL2 ('_' and '%') to Elasticsearch wildcard operators ('?' and '*', respectively). Handle escape characters and handle Elasticsearch wildcards directly.""" | ||
es_string = "" | ||
escape = False | ||
jamesfisher-geo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
for char in input_string: | ||
if char == "\\": | ||
escape = True | ||
elif char == "_" and not escape: | ||
es_string += "?" | ||
elif char == "%" and not escape: | ||
es_string += "*" | ||
else: | ||
es_string += char | ||
escape = False | ||
|
||
return es_string |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"op": "like", | ||
"args": [ | ||
{ | ||
"property": "scene_id" | ||
}, | ||
"LC82030282019133%" | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"op": "like", | ||
"args": [ | ||
{ | ||
"property": "scene_id" | ||
}, | ||
"LC82030282019133LGN0_" | ||
] | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this shouldn't be advertised unless
IN
andBETWEEN
are also implemented.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I have implemented
IN
andBETWEEN
in the latest commit.The conformance class endpoint above aligns with what STAC Browser expects. The Filter extension README has the conformance class endpoint as
http://www.opengis.net/spec/cql2/1.0/conf/advanced-comparison-operators
. Which should be used? I get a 404 response from both...I followed this example which has the
BETWEEN
bounds being passed as an array.This required adjustments to the
Clause
filter class to allow lists and some typing checks inIN
andBETWEEN
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice, will review.
Ah, that seems to be a bug in STAC Browser - they should be the urls with
conf
in them, notreq
. They aren't resolvable as a URL -- many of the OGC URL-like conformance classes aren't.This has been changed in newer versions of CQL2 (or v1.0.0-beta.5 had bad examples?). The current version of Filter Extension is here, specifically BETWEEN: https://github.com/stac-api-extensions/filter/blob/main/README.md#example-11-using-between
I think you'll probably need to make some changes to work with this instead of the beta.5 version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. Thank you, Phil.
Updated
BETWEEN
syntax and the conformance class endpoint in e7330dc