Skip to content

Commit 81a7a51

Browse files
author
Phil Varner
committed
Merge branch 'main' into pv/housekeeping
2 parents 169c657 + a3e7934 commit 81a7a51

File tree

2 files changed

+85
-33
lines changed

2 files changed

+85
-33
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
# Changelog
2+
23
All notable changes to this project will be documented in this file.
34

45
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
56
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
67

8+
## [Unreleased] - TBD
9+
10+
### Changed
11+
12+
- Basic Spatial Operators in CQL2 now only requires BBOX and POINT support, so the text
13+
and examples were updated to account for this.
14+
715
## [v1.0.0-rc.2] - 2022-11-01
816

17+
### Changed
18+
919
- Update language on catalog-level queryables
1020
- Fix several examples
1121

README.md

Lines changed: 75 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
- [STAC API - Filter Extension Specification](#stac-api---filter-extension-specification)
44
- [Overview](#overview)
55
- [Limitations of Item Search](#limitations-of-item-search)
6-
- [Filter expressiveness](#filter-expressiveness)
6+
- [Filter Expressiveness](#filter-expressiveness)
77
- [Conformance Classes](#conformance-classes)
88
- [Getting Started with Implementation](#getting-started-with-implementation)
99
- [Queryables](#queryables)
@@ -28,27 +28,30 @@
2828
- [Example 6: Temporal Intersection](#example-6-temporal-intersection)
2929
- [Example 6: T\_INTERSECTS cql2-text (GET)](#example-6-t_intersects-cql2-text-get)
3030
- [Example 6: T\_INTERSECTS cql2-json (POST)](#example-6-t_intersects-cql2-json-post)
31-
- [Example 7: Spatial Intersection](#example-7-spatial-intersection)
31+
- [Example 7: Spatial Intersection in Basic Spatial Operators](#example-7-spatial-intersection-in-basic-spatial-operators)
3232
- [Example 7: S\_INTERSECTS cql2-text (GET)](#example-7-s_intersects-cql2-text-get)
3333
- [Example 7: S\_INTERSECTS cql2-json (POST)](#example-7-s_intersects-cql2-json-post)
34-
- [Example 8: Spatial Intersection Disjunction](#example-8-spatial-intersection-disjunction)
34+
- [Example 8: Spatial Intersection in Spatial Operators](#example-8-spatial-intersection-in-spatial-operators)
3535
- [Example 8: S\_INTERSECTS cql2-text (GET)](#example-8-s_intersects-cql2-text-get)
3636
- [Example 8: S\_INTERSECTS cql2-json (POST)](#example-8-s_intersects-cql2-json-post)
37-
- [Example 9: Using IS NULL](#example-9-using-is-null)
38-
- [Example 9: cql2-text (GET)](#example-9-cql2-text-get)
39-
- [Example 9: cql2-json (POST)](#example-9-cql2-json-post)
40-
- [Example 10: Using BETWEEN](#example-10-using-between)
37+
- [Example 9: Spatial Intersection Disjunction](#example-9-spatial-intersection-disjunction)
38+
- [Example 9: S\_INTERSECTS cql2-text (GET)](#example-9-s_intersects-cql2-text-get)
39+
- [Example 9: S\_INTERSECTS cql2-json (POST)](#example-9-s_intersects-cql2-json-post)
40+
- [Example 10: Using IS NULL](#example-10-using-is-null)
4141
- [Example 10: cql2-text (GET)](#example-10-cql2-text-get)
4242
- [Example 10: cql2-json (POST)](#example-10-cql2-json-post)
43-
- [Example 11: Using LIKE](#example-11-using-like)
43+
- [Example 11: Using BETWEEN](#example-11-using-between)
4444
- [Example 11: cql2-text (GET)](#example-11-cql2-text-get)
4545
- [Example 11: cql2-json (POST)](#example-11-cql2-json-post)
46-
- [Example 12: Using the CASEI Case-insensitive Comparison Function](#example-12-using-the-casei-case-insensitive-comparison-function)
46+
- [Example 12: Using LIKE](#example-12-using-like)
4747
- [Example 12: cql2-text (GET)](#example-12-cql2-text-get)
4848
- [Example 12: cql2-json (POST)](#example-12-cql2-json-post)
49-
- [Example 13: Using the ACCENTI Accent-insensitive Comparison Function](#example-13-using-the-accenti-accent-insensitive-comparison-function)
49+
- [Example 13: Using the CASEI Case-insensitive Comparison Function](#example-13-using-the-casei-case-insensitive-comparison-function)
5050
- [Example 13: cql2-text (GET)](#example-13-cql2-text-get)
5151
- [Example 13: cql2-json (POST)](#example-13-cql2-json-post)
52+
- [Example 14: Using the ACCENTI Accent-insensitive Comparison Function](#example-14-using-the-accenti-accent-insensitive-comparison-function)
53+
- [Example 14: cql2-text (GET)](#example-14-cql2-text-get)
54+
- [Example 14: cql2-json (POST)](#example-14-cql2-json-post)
5255

5356
## Overview
5457

@@ -124,7 +127,7 @@ However, it does not contain a formalized way to filter based on arbitrary field
124127
no way to express the filter "item.properties.eo:cloud_cover is less than 10". It also does not have a way to logically combine
125128
multiple spatial or temporal filters.
126129

127-
## Filter expressiveness
130+
## Filter Expressiveness
128131

129132
This extension expands the capabilities of Item Search and the OAFeat Items resource with
130133
[OAFeat Part 3 CQL2](https://portal.ogc.org/files/96288)
@@ -187,11 +190,15 @@ For additional capabilities, the following classes may be implemented:
187190
(`http://www.opengis.net/spec/cql2/1.0/conf/advanced-comparison-operators`) defines the `LIKE`,
188191
`BETWEEN`, and `IN` operators. **Note**: this conformance class no longer requires implementing the
189192
`lower` and `upper` functions.
190-
- Basic Spatial Operators (`http://www.opengis.net/spec/cql2/1.0/conf/basic-spatial-operators`) defines the intersects operator (`S_INTERSECTS`).
193+
- Basic Spatial Operators (`http://www.opengis.net/spec/cql2/1.0/conf/basic-spatial-operators`) defines the intersects operator (`S_INTERSECTS`)
194+
that accepts only a BBOX or POINT parameter.
191195
- Spatial Operators
192196
(`http://www.opengis.net/spec/cql2/1.0/conf/spatial-operators`) defines a set of operators that
193197
are part of the Dimensionally Extended Nine-intersection Model (DE-9IM) relation operators
194-
(`S_CONTAINS`, `S_CROSSES`, `S_DISJOINT`, `S_EQUALS`, `S_INTERSECTS`, `S_OVERLAPS`, `S_TOUCHES`, and `S_WITHIN`)
198+
(`S_CONTAINS`, `S_CROSSES`, `S_DISJOINT`, `S_EQUALS`, `S_INTERSECTS`, `S_OVERLAPS`, `S_TOUCHES`, and `S_WITHIN`),
199+
and additionally defines the intersects operator (`S_INTERSECTS`) to accept LINESTRING,
200+
POLYGON, MULTIPOINT, MULTILINESTRING, and MULTIPOLYGON,
201+
in addition to BBOX and POINT as supported in Basic Spatial Operators.
195202
- Temporal Operators
196203
(`http://www.opengis.net/spec/cql2/1.0/conf/temporal-operators`) defines several temporal
197204
operators that provide more expressivity with datetime types than the relative comparison
@@ -823,21 +830,56 @@ filter=T_INTERSECTS(datetime, INTERVAL('2020-11-11T00:00:00Z', '2020-11-12T00:00
823830
}
824831
```
825832

826-
### Example 7: Spatial Intersection
833+
### Example 7: Spatial Intersection in Basic Spatial Operators
827834

828835
The only spatial operator that must be implemented for Basic Spatial Operators
829-
is `S_INTERSECTS`. This has the same semantics as provided
836+
is `S_INTERSECTS` supporting BBOX and POINT. This has the same semantics as provided
830837
by the Item Search `intersects` parameter. The `cql2-text` format uses WKT geometries and the `cql2-json`
831838
format uses GeoJSON geometries.
832839

833840
#### Example 7: S_INTERSECTS cql2-text (GET)
834841

835842
```text
843+
<<<<<<< HEAD
836844
filter=S_INTERSECTS(geometry,POLYGON((-77.0824 38.7886,-77.0189 38.7886,-77.0189 38.8351,-77.0824 38.8351,-77.0824 38.7886)))
845+
=======
846+
filter=S_INTERSECTS(geometry,POINT(-77.0824 38.7886))
847+
>>>>>>> main
837848
```
838849

839850
#### Example 7: S_INTERSECTS cql2-json (POST)
840851

852+
```json
853+
{
854+
"filter-lang": "cql2-json",
855+
"filter": {
856+
"op": "s_intersects",
857+
"args": [
858+
{ "property": "geometry" } ,
859+
{
860+
"type": "Point",
861+
"coordinates": [-77.0824, 38.7886]
862+
}
863+
]
864+
}
865+
}
866+
```
867+
868+
### Example 8: Spatial Intersection in Spatial Operators
869+
870+
The Spatial Operators extends the Basic Spatial Operators by adding support for additional
871+
geometries to the `S_INTERSECTS` parameter. This has the same semantics as provided
872+
by the Item Search `intersects` parameter. The `cql2-text` format uses WKT geometries and the `cql2-json`
873+
format uses GeoJSON geometries.
874+
875+
#### Example 8: S_INTERSECTS cql2-text (GET)
876+
877+
```text
878+
filter=S_INTERSECTS(geometry,POLYGON((-77.0824 38.7886,-77.0189 38.7886,-77.0189 38.8351,-77.0824 38.8351,-77.0824 38.7886)))
879+
```
880+
881+
#### Example 8: S_INTERSECTS cql2-json (POST)
882+
841883
```json
842884
{
843885
"filter-lang": "cql2-json",
@@ -858,20 +900,20 @@ filter=S_INTERSECTS(geometry,POLYGON((-77.0824 38.7886,-77.0189 38.7886,-77.0189
858900
}
859901
```
860902

861-
### Example 8: Spatial Intersection Disjunction
903+
### Example 9: Spatial Intersection Disjunction
862904

863905
One limitation of the `intersects` parameter is that only a single geometry may be provided. While most
864906
GeoJSON geometries can be combined to form a composite (e.g., multiple Polygons can be combined to form a
865907
MultiPolygon), this is much easier to do in the query by combining `S_INTERSECTS` predicates with the `OR`
866908
logical operator.
867909

868-
#### Example 8: S_INTERSECTS cql2-text (GET)
910+
#### Example 9: S_INTERSECTS cql2-text (GET)
869911

870912
```text
871913
filter=S_INTERSECTS(geometry,POLYGON((-77.0824 38.7886,-77.0189 38.7886,-77.0189 38.8351,-77.0824 38.8351,-77.0824 38.7886))) OR S_INTERSECTS(geometry,POLYGON((-79.0935 38.7886,-79.0290 38.7886,-79.0290 38.8351,-79.0935 38.8351,-79.0935 38.7886)))
872914
```
873915

874-
#### Example 8: S_INTERSECTS cql2-json (POST)
916+
#### Example 9: S_INTERSECTS cql2-json (POST)
875917

876918
```json
877919
{
@@ -912,7 +954,7 @@ filter=S_INTERSECTS(geometry,POLYGON((-77.0824 38.7886,-77.0189 38.7886,-77.0189
912954
}
913955
```
914956

915-
### Example 9: Using IS NULL
957+
### Example 10: Using IS NULL
916958

917959
One of the main use cases for STAC API is doing cross-collection query. Commonly, this means that items have
918960
different sets of properties. For example, a collection of Sentinel 2 data may have a property
@@ -921,13 +963,13 @@ different sets of properties. For example, a collection of Sentinel 2 data may h
921963
data. However, we many also want to also include in our result items that do not have a value defined for
922964
either of those properties.
923965

924-
#### Example 9: cql2-text (GET)
966+
#### Example 10: cql2-text (GET)
925967

926968
```text
927969
filter=sentinel:data_coverage > 50 OR landsat:coverage_percent < 10 OR (sentinel:data_coverage IS NULL AND landsat:coverage_percent IS NULL)
928970
```
929971

930-
#### Example 9: cql2-json (POST)
972+
#### Example 10: cql2-json (POST)
931973

932974
```json
933975
{
@@ -961,17 +1003,17 @@ filter=sentinel:data_coverage > 50 OR landsat:coverage_percent < 10 OR (sentinel
9611003
}
9621004
```
9631005

964-
### Example 10: Using BETWEEN
1006+
### Example 11: Using BETWEEN
9651007

9661008
The BETWEEN operator allows for checking if a numeric value is within a specified inclusive range.
9671009

968-
#### Example 10: cql2-text (GET)
1010+
#### Example 11: cql2-text (GET)
9691011

9701012
```text
9711013
filter=eo:cloud_cover BETWEEN 0 AND 50
9721014
```
9731015

974-
#### Example 10: cql2-json (POST)
1016+
#### Example 11: cql2-json (POST)
9751017

9761018
```json
9771019
{
@@ -986,17 +1028,17 @@ filter=eo:cloud_cover BETWEEN 0 AND 50
9861028
}
9871029
```
9881030

989-
### Example 11: Using LIKE
1031+
### Example 12: Using LIKE
9901032

9911033
The LIKE operator allows for pattern-based string matching.
9921034

993-
#### Example 11: cql2-text (GET)
1035+
#### Example 12: cql2-text (GET)
9941036

9951037
```text
9961038
filter=mission LIKE 'sentinel%'
9971039
```
9981040

999-
#### Example 11: cql2-json (POST)
1041+
#### Example 12: cql2-json (POST)
10001042

10011043
```json
10021044
{
@@ -1011,7 +1053,7 @@ filter=mission LIKE 'sentinel%'
10111053
}
10121054
```
10131055

1014-
### Example 12: Using the CASEI Case-insensitive Comparison Function
1056+
### Example 13: Using the CASEI Case-insensitive Comparison Function
10151057

10161058
The predefined function `CASEI` allows for case-insensitive comparisons. This function is
10171059
defined in the Accent and Case-insensitive Comparison conformance class.
@@ -1020,7 +1062,7 @@ In the example using 'Straße', both the capitalized 'S' and Eszett ('ß') are c
10201062
insensitive representation whereby the expressions `CASEI('Straße')`, `CASEI('straße')`,
10211063
`CASEI('Strasse')`, and `CASEI('strasse')` are all equal.
10221064

1023-
#### Example 12: cql2-text (GET)
1065+
#### Example 13: cql2-text (GET)
10241066

10251067
```text
10261068
filter=CASEI(provider) = CASEI('coolsat')
@@ -1030,7 +1072,7 @@ filter=CASEI(provider) = CASEI('coolsat')
10301072
filter=CASEI(provider) = CASEI('Straße')
10311073
```
10321074

1033-
#### Example 12: cql2-json (POST)
1075+
#### Example 13: cql2-json (POST)
10341076

10351077
```json
10361078
{
@@ -1070,19 +1112,19 @@ filter=CASEI(provider) = CASEI('Straße')
10701112
}
10711113
```
10721114

1073-
### Example 13: Using the ACCENTI Accent-insensitive Comparison Function
1115+
### Example 14: Using the ACCENTI Accent-insensitive Comparison Function
10741116

10751117
The predefined function `ACCENTI` allows for accent-insensitive comparisons. This function is
10761118
defined in the Accent and Case-insensitive Comparison conformance class. In the example below,
10771119
`ACCENTI('tiburon')` and `ACCENTI('tiburón')` evaluate to be equal.
10781120

1079-
#### Example 13: cql2-text (GET)
1121+
#### Example 14: cql2-text (GET)
10801122

10811123
```text
10821124
filter=ACCENTI(provider) = ACCENTI('tiburón')
10831125
```
10841126

1085-
#### Example 13: cql2-json (POST)
1127+
#### Example 14: cql2-json (POST)
10861128

10871129
```json
10881130
{

0 commit comments

Comments
 (0)