From f0c1597b05b1946b3e129635566ddf77d4039c67 Mon Sep 17 00:00:00 2001 From: Phil Varner Date: Mon, 23 Aug 2021 17:03:10 -0400 Subject: [PATCH 01/14] align conformance classes to latest OGC API Features CQL2 spec --- CHANGELOG.md | 16 ++- extensions.md | 10 +- fragments/filter/README.md | 253 +++++++++++++++++-------------------- 3 files changed, 143 insertions(+), 136 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a08e4299..01b60644 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,26 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [Unreleased - v1.0.0-beta4] - TBD ### Added ### Changed +- Filter Extension - query language is now referred to as "CQL2" rather than CQL +- Filter Extension - The following changes have been made to the Filter Extension conformance classes to align with changes to the OAFeat CQL draft. All classes + whose names have changed also have changed conformance URI strings. + - "Basic CQL" now includes the "not equal" operator (`<>`) + - "Basic CQL" has always supported datetime comparisons, but this is now explicitly mentioned + - "Enhanced Comparison Operators" has been renamed "Advanced Comparison Operators". This is the same as the OAFeat CQL definition, except + that it does not require the `upper` and `lower` functions. + - "Enhanced Spatial Operators" has been renamed to just "Spatial Operators" (not to be confused with Basic Spatial Operators) + - "Basic Temporal Operators" and "Enhanced Temporal Operators" have merged into "Temporal Operators" + - "Functions" has been renamed "Custom Functions" + - "Arithmetic" has been renamed "Arithmetic Expressions" + - "Arrays" has been renamed "Array Operators" + - "Queryable Second Operand" has been renamed "Property-Property Comparisons" + ### Deprecated ### Removed diff --git a/extensions.md b/extensions.md index 035a93bb..323c9015 100644 --- a/extensions.md +++ b/extensions.md @@ -69,10 +69,18 @@ the service supports. This are listed at the top of each extension description, - - [Filter](item-search/README.md#filter) - - - + - - - - + - + - + - + - + - + - + - + - - [Context](item-search/README.md#context) - - [Sort](item-search/README.md#sort) diff --git a/fragments/filter/README.md b/fragments/filter/README.md index dd2d7270..f8ca7f67 100644 --- a/fragments/filter/README.md +++ b/fragments/filter/README.md @@ -4,18 +4,17 @@ - **Conformance Classes:** - Filter: - Item Search Filter: - - CQL Text: - - CQL JSON: - - Basic CQL: + - CQL2 Text: + - CQL2 JSON: + - Basic CQL2: + - Advanced Comparison Operators: - Basic Spatial Operators: - - Basic Temporal Operators: - - Enhanced Comparison Operators: - - Enhanced Spatial Operators: - - Enhanced Temporal Operators: - - Functions: - - Arithmetic: - - Arrays: - - Queryable Second Operand: + - Spatial Operators: + - Temporal Operators: + - Custom Functions: + - Arithmetic Expressions: + - Array Operators: + - Property-Property Comparisons: - **Extension [Maturity Classification](../../extensions.md#extension-maturity):** Pilot - **Dependents:** - [Item Search](../../item-search) @@ -31,41 +30,41 @@ - [Interaction with Endpoints](#interaction-with-endpoints) - [Examples](#examples) - [Example 1](#example-1) - - [Example 1: GET with cql-text](#example-1-get-with-cql-text) - - [Example 1: POST with cql-json](#example-1-post-with-cql-json) + - [Example 1: GET with cql2-text](#example-1-get-with-cql2-text) + - [Example 1: POST with cql2-json](#example-1-post-with-cql2-json) - [Example 2](#example-2) - - [Example 2: GET with cql-text](#example-2-get-with-cql-text) - - [Example 2: POST with cql-json](#example-2-post-with-cql-json) + - [Example 2: GET with cql2-text](#example-2-get-with-cql2-text) + - [Example 2: POST with cql2-json](#example-2-post-with-cql2-json) - [Example 3](#example-3) - - [Example 3: GET with cql-text](#example-3-get-with-cql-text) - - [Example 3: POST with cql-json](#example-3-post-with-cql-json) + - [Example 3: GET with cql2-text](#example-3-get-with-cql2-text) + - [Example 3: POST with cql2-json](#example-3-post-with-cql2-json) - [Example 4](#example-4) - - [Example 4: AND cql-text (GET)](#example-4-and-cql-text-get) - - [Example 4: AND cql-json (POST)](#example-4-and-cql-json-post) + - [Example 4: AND cql2-text (GET)](#example-4-and-cql2-text-get) + - [Example 4: AND cql2-json (POST)](#example-4-and-cql2-json-post) - [Example 5](#example-5) - - [Example 5: OR cql-text (GET)](#example-5-or-cql-text-get) - - [Example 5: OR cql-json (POST)](#example-5-or-cql-json-post) + - [Example 5: OR cql2-text (GET)](#example-5-or-cql2-text-get) + - [Example 5: OR cql2-json (POST)](#example-5-or-cql2-json-post) - [Example 6: Temporal](#example-6-temporal) - - [Example 6: ANYINTERACTS cql-text (GET)](#example-6-anyinteracts-cql-text-get) - - [Example 6: ANYINTERACTS cql-json (POST)](#example-6-anyinteracts-cql-json-post) + - [Example 6: ANYINTERACTS cql2-text (GET)](#example-6-anyinteracts-cql2-text-get) + - [Example 6: ANYINTERACTS cql2-json (POST)](#example-6-anyinteracts-cql2-json-post) - [Example 6: Spatial](#example-6-spatial) - - [Example 6: INTERSECTS cql-text (GET)](#example-6-intersects-cql-text-get) - - [Example 6: INTERSECTS cql-json (POST)](#example-6-intersects-cql-json-post) + - [Example 6: INTERSECTS cql2-text (GET)](#example-6-intersects-cql2-text-get) + - [Example 6: INTERSECTS cql2-json (POST)](#example-6-intersects-cql2-json-post) ## Overview The Filter extension provides an expressive mechanism for searching based on Item attributes. This extension references behavior defined in the -[OGC API - Features - Part 3: Filtering and the Common Query Language (CQL)](https://portal.ogc.org/files/96288) -specification. As of July 2021, this specification is in draft status. The only major anticipated change before final -is to the division of behavior among conformance classes, as described -in the [Conformance Classes](#conformance-classes) section. While this makes implementing this spec somewhat of a moving -target, implementers are encouraged to move ahead with support with the expectation that they will be able to precisely -advertise behavior through conformance classes prior to STAC API 1.0.0 final. - -OAFeat Part 3 CQL formally defines the syntax of "CQL2" as both a text format (cql-text) as an ABNF grammar -(largely similar to the BNF grammar in the General Model for CQL) and a JSON format (cql-json) as a JSON Schema and +[OGC API - Features - Part 3: Filtering and the Common Query Language (CQL2)](https://github.com/opengeospatial/ogcapi-features/tree/master/extensions/cql) +specification. As of August 2021, this specification is in draft status. Several behaviors have changed since the +last published [draft](https://portal.ogc.org/files/96288), so this spec references the latest revision in the +[spec's GitHub repo](https://github.com/opengeospatial/ogcapi-features/tree/master/extensions/cql). There are no +major anticipated changes, so implementers are encouraged to move ahead with implementation, and to simply be +aware that minor changes may need to be made in the future. + +OAFeat Part 3 CQL2 formally defines the syntax of "CQL2" as both a text format (cql2-text) as an ABNF grammar +(largely similar to the BNF grammar in the General Model for CQL) and a JSON format (cql2-json) as a JSON Schema and OpenAPI schema, and provides a precise natural language description of the declarative semantics. The CQL Text format has long-standing use within geospatial software (e.g., GeoServer), is expected not to change before final. @@ -74,7 +73,7 @@ OGC CQL Text has been previously described in [OGC Filter Encoding](https://www. (including a BNF grammar in Annex B). The CQL JSON format is newly-defined, but also not expected to change before final. -It should be noted that the "CQL" referred to here is "CQL2" defined in OGC API Features Part 3 CQL. This is a related, but +It should be noted that the "CQL" referred to here is "CQL2" defined in OGC API - Features - Part 3. This is a related, but different language to the "classic" OGC CQL defined in the General Model. CQL is also **not** referencing or related two other "CQL" languages, the [SRU (Search/Retrieve via URL) Contextual Query Language](https://www.loc.gov/standards/sru/cql/index.html) (formerly @@ -96,28 +95,21 @@ However, it does not contain a formalized way to filter based on arbitrary field 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 multiple spatial or temporal filters. -## Filter expressiveness +## Filter expressiveness This extension expands the capabilities of Item Search and the OAFeat Items resource with -[OAFeat Part 3 CQL](https://portal.ogc.org/files/96288) -by providing an expressive query language to construct more complex filter predicates. The operators are similar to -those provided by SQL. The Basic CQL conformance class requires the logical operators `AND`, `OR`, and `NOT`; -the comparison operators `=`, `<`, `<=`, `>`, `>=`; and the `IS NULL` operator. Other conformance classes add additional -filtering capabilities. - -The `ANYINTERACTS` operator has effectively the same semantics as the `datetime` parameter -in Item Search. +[OAFeat Part 3 CQL2](https://portal.ogc.org/files/96288) +by providing an expressive query language to construct more complex filter predicates using operators that are similar to +those provided by SQL. This extension also supports the Queryables mechanism that allows discovery of what Item fields can be used in +predicates. -CQL enables these types of queries: +CQL enables more expressive queries than supported by STAC API Item Search. These include: - Use of Item Property values in predicates (e.g., `item.properties.eo:cloud_cover`), using comparison operators -- Items whose `datetime` values are in the month of August of the years 2017-2021, using OR and ANYINTERACTS +- Items whose `datetime` values are in the month of August of the years 2017-2021, using OR and datetime comparisons - Items whose `geometry` values intersect any one of several Polygons, using OR and INTERSECTS - Items whose `geometry` values intersect one Polygon, but do not intersect another one, using AND, NOT, and INTERSECTS -This extension also supports the Queryables mechanism that allows discovery of what Item fields can be used in -predicates. - ## Conformance Classes OAFeat CQL defines several conformance classes that allow implementers to create compositions of @@ -125,68 +117,57 @@ functionality that support whatever expressiveness they need. This allows implem syntax, without needing to implement a huge spec all at once. Some implementers choose not to incur the cost of implementing functionality they do not need or may not be able to implement functionality that is not supported by their underlying datastore, e.g., Elasticsearch does not support the spatial predicates required by the -Enhanced Spatial Operators conformance class. +Spatial Operators conformance class, only the `intersects` operator in the Basic Spatial Operators class. -The precise decomposition of the OAFeat conformance classes is still a work in progress +The precise decomposition of the OAFeat conformance classes is still a work in progress, but rapidly being finalized (see [ogcapi-features/issues/579](https://github.com/opengeospatial/ogcapi-features/issues/579)). -The STAC API Filter Extension reuses the definitions in OAFeat CQL, but divides them into different conformance classes -that better fit the use cases of STAC API. This extension uses conformance classes with a prefix of -`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:`. We hope the conformance -classes defined here and in OGC API Features Part 3 will re-align at some point but, for now, they do not. +The STAC API Filter Extension reuses the definitions and conformance classes in OAFeat CQL, with a single minor exception +described below. This extension uses conformance classes with a prefix of `https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:`. The implementation **must** support these conformance classes: - Filter (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:filter`) defines the Queryables mechanism and parameters `filter-lang`, `filter-crs`, and `filter`. -- Basic CQL (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:basic-cql`) defines the basic operations allowed in +- Basic CQL2 (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:basic-cql2`) defines the basic operations allowed in the query language used for the `filter` parameter defined by Filter. This includes logical operators (`AND`, `OR`, `NOT`), - comparison operators (`=`, `<`, `<=`, `>`, `>=`), and `IS NULL`. + comparison operators (`=`, `<>`, `<`, `<=`, `>`, `>=`), and `IS NULL`. The comparison operators are allowed against string, numeric, boolean, + and datetime types. - Item Search Filter (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:item-search-filter`) binds the Filter and - Basic CQL conformance classes to apply to the Item Search endpoint (`/search`). This class is the correlate of the OAFeat CQL Features - Filter class that binds Filter and Basic CQL to the Features resource (`/collections/{cid}/items`). - -It is **recommended** that the implementation also support the Basic Spatial Operators and Basic Temporal Operators classes: + Basic CQL2 conformance classes to apply to the Item Search endpoint (`/search`). This class is the correlate of the OAFeat CQL Features + Filter class that binds Filter and Basic CQL2 to the Features resource (`/collections/{cid}/items`). -- Basic Spatial Operators (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:basic-spatial-operators`) - defines the `INTERSECTS` predicate -- Basic Temporal Operators: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:basic-temporal-operators`) - defines the `ANYINTERACTS` predicate - -Additionally, the implementation **must** support at least one of the "CQL Text" or "CQL JSON" conformance classes that define +The implementation **must** support at least one of the "CQL2 Text" or "CQL2 JSON" conformance classes that define the CQL format used in the filter parameter: -- CQL Text (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql-text`) defines that the CQL Text format is supported by Item Search. -- CQL JSON (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql-json`) defines that the CQL JSON format is supported by Item Search +- CQL2 Text (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql2-text`) defines that the CQL2 Text format is supported by Item Search +- CQL JSON (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql2-json`) defines that the CQL JSON format is supported by Item Search If both are advertised as being supported, it is only required that both be supported for GET query parameters, and that -only that CQL JSON be supported for POST JSON requests. It is recommended that clients use CQL Text in GET requests and +only that CQL JSON be supported for POST JSON requests. It is recommended that clients use CQL2 Text in GET requests and CQL JSON in POST requests. -The Filter Extension defines support for implementing the following conformance -classes. Implementation of these is often limited by the -operations supported by the implementation's datastore, for example, Elasticsearch does not support the spatial -operations required by the Enhanced Spatial Operators. If implemented for Item Search, the conformance class -URI should follow the same pattern relative to OAFeat CQL. - -- Enhanced Comparison Operators - (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:enhanced-comparison-operators`) defines the `LIKE`, - `BETWEEN`, and `IN` operators. It is **recommended** to implement this class. -- Enhanced Spatial Operators - (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:enhanced-spatial-operators`) defines the - same operators as OAF Part 3 CQL Enhanced Spatial Operators. -- Enhanced Temporal Operators - (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:enhanced-temporal-operators`) defines the +For additional capabilities, the following classes can be implemented: +- Advanced Comparison Operators + (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:advanced-comparison-operators`) defines the `LIKE`, + `BETWEEN`, and `IN` operators. This conformance class in Filter Extension does **not** require implementing `lower` and + `upper` functions as the OAFeat CQL conformance class requires. +- Basic Spatial Operators (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:basic-spatial-operators`) defines the `INTERSECTS` predicate. +- Spatial Operators + (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:spatial-operators`) defines the + same operators as OAF Part 3 CQL Advanced Spatial Operators. +- Temporal Operators + (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:temporal-operators`) defines the same operators as OAF Part 3 CQL Enhanced Temporal Operators. -- Functions (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:functions`) defines the same operators as OAF Part 3 CQL Functions. -- Arithmetic: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:arithmetic`) defines the same operators as OAF Part 3 CQL Arithmetic. -- Arrays: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:arrays`) defines the same operators as OAF Part 3 CQL Arrays. -- Queryable Second Operand: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:queryable-second-operand`) allows the - use of queryables (e.g., properties) in any position of a clause, not just in the first position. This allows - predicates like `property1 == property2` be expressed, whereas the Basic CQL conformance class only requires +- Custom Functions (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:custom-functions`) defines the same operators as OAF Part 3 CQL Custom Functions. +- Arithmetic Expressions: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:arithmetic-expressions`) defines the same operators as OAF Part 3 CQL Arithmetic Expressions. +- Array Operators: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:array-operators`) defines the same operators as OAF Part 3 CQL Array Operators. +- Property-Property Comparisons: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:property-property-comparisons`) allows the + use of queryables (e.g., properties) in both positions of a clause, not just in the first position. This allows + predicates like `property1 == property2` be expressed, whereas the Basic CQL2 conformance class only requires comparisons against literal values. Additionally, if an API implements the OGC API Features endpoint, it is **recommended** that the OAFeat Part 3 Filter, -Features Filter, and Basic CQL conformance classes be implemented, which allow use of CQL filters against the +Features Filter, and Basic CQL2 conformance classes be implemented, which allow use of CQL filters against the OAFeat Part 1 Features endpoint (`/collections/{collectionId}/items`). Note that POST with a JSON body to the Features resource is not supported, as POST is used by the [Transaction Extension](../../ogcapi-features/extensions/transaction/README.md) for creating items. @@ -194,16 +175,16 @@ to the Features resource is not supported, as POST is used by the ## Getting Started with Implementation It recommended that implementers start with fully implementing only a subset of functionality. A good place to start is -implementing only the Basic CQL conformance class of logical and comparison operators, defining a static Queryables -schema with no queryables advertised, and only implementing CQL Text. Following from that can be support for -INTERSECTS and ANYINTERACTS, defining a static Queryables schema with only the basic Item properties, and also +implementing only the Basic CQL2 conformance class of logical and comparison operators, defining a static Queryables +schema with no queryables advertised, and only implementing CQL2 Text. Following from that can be support for +INTERSECTS, defining a static Queryables schema with only the basic Item properties, and implementing CQL JSON. From there, other comparison operators can be implemented and a more -dynamic Queryables schema (if desired). +dynamic Queryables schema. Formal definitions and grammars for CQL can be found here: -- The [OAFeat (CQL) spec](https://portal.ogc.org/files/96288) includes an ABNF for cql-text and both JSON Schema and - OpenAPI specifications for cql-json. The standalone files are: +- The [OAFeat (CQL) spec](https://portal.ogc.org/files/96288) includes an ABNF for cql2-text and both JSON Schema and + OpenAPI specifications for cql2-json. The standalone files are: - [cql.bnf](https://github.com/opengeospatial/ogcapi-features/blob/master/extensions/cql/standard/schema/cql.bnf) - [cql.json](https://github.com/opengeospatial/ogcapi-features/blob/master/extensions/cql/standard/schema/cql.json) - [cql.yml](https://github.com/opengeospatial/ogcapi-features/blob/master/extensions/cql/standard/schema/cql.yml) @@ -329,15 +310,15 @@ in STAC API by the Filter Extension. In this case, the queryables endpoint (`/qu This extension adds three GET query parameters or POST JSON fields to an Item Search request: -- filter-lang:`cql-text` or `cql-json`. If undefined, defaults to `cql-text` for a GET request and `cql-json` for a POST request. +- filter-lang:`cql2-text` or `cql2-json`. If undefined, defaults to `cql2-text` for a GET request and `cql2-json` for a POST request. - filter-crs: recommended to not be passed, but server must only accept `http://www.opengis.net/def/crs/OGC/1.3/CRS84` as a valid value, may reject any others - filter: CQL filter expression API implementations advertise which `filter-lang` values are supported via conformance classes in the Landing Page. At least one must be implemented, but it is recommended to implement both. If both are advertised as conformance classes, the -server should process either for a GET request, but may only process cql-json for a POST request. If POST of cql-text is not -supported, the server must return a 400 error if `filter-lang=cql-text`. +server should process either for a GET request, but may only process cql2-json for a POST request. If POST of cql2-text is not +supported, the server must return a 400 error if `filter-lang=cql2-text`. ## Interaction with Endpoints @@ -360,12 +341,11 @@ at least these values: "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:filter", "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:features-filter", - "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:basic-cql", - "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql-text", - "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql-json", + "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:basic-cql2", + "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql2-text", + "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql2-json", "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:basic-spatial-operators", - "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:basic-temporal-operators", - "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:enhanced-comparison-operators" + "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:advanced-comparison-operators" ], "links": [ @@ -459,18 +439,18 @@ in any of these examples. This example uses the queryables definition in (Interaction with Endpoints)(#interaction-with-endpoints). -#### Example 1: GET with cql-text +#### Example 1: GET with cql2-text -Note that `filter-lang` defaults to `cql-text` in this case. The parameter `filter-crs` defaults +Note that `filter-lang` defaults to `cql2-text` in this case. The parameter `filter-crs` defaults to `http://www.opengis.net/def/crs/OGC/1.3/CRS84` for a STAC API. ```javascript GET /search?filter=id='LC08_L1TP_060247_20180905_20180912_01_T1_L1TP' AND collection='landsat8_l1tp' ``` -#### Example 1: POST with cql-json +#### Example 1: POST with cql2-json -Note that `filter-lang` defaults to `cql-json` in this case. The parameter `filter-crs` defaults +Note that `filter-lang` defaults to `cql2-json` in this case. The parameter `filter-crs` defaults to `http://www.opengis.net/def/crs/OGC/1.3/CRS84` for a STAC API. ```javascript @@ -498,22 +478,23 @@ This example uses the queryables definition in [Interaction with Endpoints](#int Note that filtering on the `collection` field is relevant in Item Search, since the queries are cross-collection, whereas OGC API Features filters only operate against a single collection already. -#### Example 2: GET with cql-text +#### Example 2: GET with cql2-text ```javascript -GET /search?filter=collection = 'landsat8_l1tp' +GET /search?filter=collection = 'landsat8_l1tp' AND gsd <= 30 - AND eo:cloud_cover <= 10 - AND datetime ANYINTERACTS 2021-04-08T04:39:23Z/2021-05-07T12:27:57Z - AND INTERSECTS(geometry, POLYGON((43.5845 -79.5442, 43.6079 -79.4893, 43.5677 -79.4632, 43.6129 -79.3925, 43.6223 -79.3238, 43.6576 -79.3163, 43.7945 -79.1178, 43.8144 -79.1542, 43.8555 -79.1714, 43.7509 -79.6390, 43.5845 -79.5442)) + AND eo:cloud_cover <= 10 + AND datetime >= "2021-04-08T04:39:23Z" + AND datetime <= "2021-05-07T12:27:57Z" + AND INTERSECTS(geometry, POLYGON((43.5845 -79.5442, 43.6079 -79.4893, 43.5677 -79.4632, 43.6129 -79.3925, 43.6223 -79.3238, 43.6576 -79.3163, 43.7945 -79.1178, 43.8144 -79.1542, 43.8555 -79.1714, 43.7509 -79.6390, 43.5845 -79.5442)) ``` -#### Example 2: POST with cql-json +#### Example 2: POST with cql2-json ```javascript POST /search { - "filter-lang": "cql-json", + "filter-lang": "cql2-json", "filter": { "and": [ "eq": [ @@ -524,9 +505,13 @@ POST /search { "property": "eo:cloud_cover" }, "10" ], - "anyinteracts": [ + "gte": [ + { "property": "datetime" }, + "2021-04-08T04:39:23Z" + ], + "lte": [ { "property": "datetime" }, - [ "2021-04-08T04:39:23Z", "2021-05-07T12:27:57Z" ] + "2021-05-07T12:27:57Z" ], "intersects": [ { "property": "geometry" }, @@ -582,18 +567,18 @@ This queryables JSON Schema is used in these examples: } ``` -#### Example 3: GET with cql-text +#### Example 3: GET with cql2-text ```javascript GET /search?filter=prop1 = prop2 ``` -#### Example 3: POST with cql-json +#### Example 3: POST with cql2-json ```javascript POST /search { - "filter-lang": "cql-json", + "filter-lang": "cql2-json", "filter": { "eq": [ { "property": "prop1" }, @@ -695,13 +680,13 @@ recording path intersection only a corner of a grid square. This examples shows Show me all imagery that has low cloud cover (less than 10), and high data coverage (50), as I'd like a cloud free image that is not just a tiny sliver of data. -#### Example 4: AND cql-text (GET) +#### Example 4: AND cql2-text (GET) ```javascript /search?filter=sentinel:data_coverage > 50 AND eo:cloud_cover < 10 ``` -#### Example 4: AND cql-json (POST) +#### Example 4: AND cql2-json (POST) ```json { @@ -735,13 +720,13 @@ coverage or low cloud cover. This uses the same queryables as Example 4. -#### Example 5: OR cql-text (GET) +#### Example 5: OR cql2-text (GET) ```javascript /search?filter=sentinel:data_coverage > 50 OR eo:cloud_cover < 10 ``` -#### Example 5: OR cql-json (POST) +#### Example 5: OR cql2-json (POST) ```json { @@ -768,23 +753,23 @@ This uses the same queryables as Example 4. This uses the same queryables as Example 4. -The only temporal operator required is `ANYINTERACTS`, which follows the same semantics as the existing -`datetime` parameter. This is effectively that the datetime or interval operands have any overlap between them. +The only temporal operator required is `ANYINTERACTS`. This is effectively that the datetime or interval operands +have any overlap between them. -#### Example 6: ANYINTERACTS cql-text (GET) +#### Example 6: ANYINTERACTS cql2-text (GET) ```javascript -/search?filter=datetime ANYINTERACTS 2020-11-11 +/search?filter=datetime ANYINTERACTS 2020-11-11T00:00:00Z/2020-11-12T00:00:00Z ``` -#### Example 6: ANYINTERACTS cql-json (POST) +#### Example 6: ANYINTERACTS cql2-json (POST) ```json { "filter": { "anyinteracts": [ { "property": "datetime" }, - "2020-11-11" + [ "2020-11-11T00:00:00Z", "2020-11-12T00:00:00Z"] ] } } @@ -793,16 +778,16 @@ The only temporal operator required is `ANYINTERACTS`, which follows the same se ### Example 6: Spatial The only spatial operator that must be implemented is `INTERSECTS`. This has the same semantics as the one provided -in the Item Search `intersects` parameter. The `cql-text` format uses WKT geometries and the `cql-json` format uses +in the Item Search `intersects` parameter. The `cql2-text` format uses WKT geometries and the `cql2-json` format uses GeoJSON geometries. -#### Example 6: INTERSECTS cql-text (GET) +#### Example 6: INTERSECTS cql2-text (GET) ```javascript /search?filter=INTERSECTS(geometry,POLYGON((-77.0824 38.7886,-77.0189 38.7886,-77.0189 38.8351,-77.0824 38.8351,-77.0824 38.7886))) ``` -#### Example 6: INTERSECTS cql-json (POST) +#### Example 6: INTERSECTS cql2-json (POST) ```json { From 361f0cc8770937ac694f84b702e6ae86211e6b50 Mon Sep 17 00:00:00 2001 From: Phil Varner Date: Mon, 23 Aug 2021 18:04:31 -0400 Subject: [PATCH 02/14] change cql to cql2 --- extensions.md | 4 ++-- fragments/filter/openapi.yaml | 18 +++++++++--------- item-search/README.md | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/extensions.md b/extensions.md index 323c9015..e3198685 100644 --- a/extensions.md +++ b/extensions.md @@ -71,8 +71,8 @@ the service supports. This are listed at the top of each extension description, - - - - - - - + - + - - - - diff --git a/fragments/filter/openapi.yaml b/fragments/filter/openapi.yaml index be5fe32e..0636a1a9 100644 --- a/fragments/filter/openapi.yaml +++ b/fragments/filter/openapi.yaml @@ -103,8 +103,8 @@ components: required: true schema: oneOf: - - $ref: '#/components/schemas/filter-cql-json' - - $ref: '#/components/schemas/filter-cql-text' + - $ref: '#/components/schemas/filter-cql2-json' + - $ref: '#/components/schemas/filter-cql2-text' filter-lang: name: filter-lang x-stac-api-fragment: filter @@ -112,7 +112,7 @@ components: description: |- **Extension:** Filter - The CQL filter encoding that the 'filter' value uses. Must be one of 'cql-text' or 'cql-json'. + The CQL filter encoding that the 'filter' value uses. Must be one of 'cql2-text' or 'cql2-json'. required: false schema: $ref: '#/components/schemas/filter-lang' @@ -138,24 +138,24 @@ components: A filter for properties in Items. properties: filter: - $ref: '#/components/schemas/filter-cql-json' + $ref: '#/components/schemas/filter-cql2-json' filter-lang: $ref: '#/components/schemas/filter-lang' filter-crs: $ref: '#/components/schemas/filter-crs' - filter-cql-text: + filter-cql2-text: description: | - A CQL filter expression in the 'cql-text' encoding. + A CQL filter expression in the 'cql2-text' encoding. type: string - filter-cql-json: + filter-cql2-json: $ref: './cql.yml#/components/schemas/booleanValueExpression' filter-lang: description: | The CQL filter encoding that the 'filter' value uses. type: string enum: - - 'cql-text' - - 'cql-json' + - 'cql2-text' + - 'cql2-json' filter-crs: description: | The coordinate reference system (CRS) used by spatial literals in the 'filter' value. The only value that STAC APIs must diff --git a/item-search/README.md b/item-search/README.md index 8dcf2bf2..d2065b70 100644 --- a/item-search/README.md +++ b/item-search/README.md @@ -317,7 +317,7 @@ through the use of a `fields` parameter. The full description of how this extens The STAC search endpoint, `/search`, by default only accepts a limited set of parameters to limit the results by properties. The Filter extension adds a new parameter, `filter`, that can take a number of comparison operators to match predicates between the fields requested and the values of Item objects. It can be used with both GET and POST and supports two -query formats, `cql-text` and `cql-json`. The full details on the JSON structure are specified in the [filter +query formats, `cql2-text` and `cql2-json`. The full details on the JSON structure are specified in the [filter fragment](../fragments/filter/). ### Sort From 047f9d0411b0d7a8a14c7e828b3a14aee9b21fdf Mon Sep 17 00:00:00 2001 From: Phil Varner Date: Tue, 24 Aug 2021 09:45:01 -0400 Subject: [PATCH 03/14] align conformance class URIs to OAFeat --- extensions.md | 14 ++-- fragments/filter/README.md | 124 +++++++++++++++++----------------- fragments/filter/openapi.yaml | 18 ++--- item-search/README.md | 2 +- 4 files changed, 79 insertions(+), 79 deletions(-) diff --git a/extensions.md b/extensions.md index e3198685..6b32e648 100644 --- a/extensions.md +++ b/extensions.md @@ -69,18 +69,18 @@ the service supports. This are listed at the top of each extension description, - - [Filter](item-search/README.md#filter) - - - + - - - - - - + - + - - - - - - - - - - - - - + - + - + - + - - [Context](item-search/README.md#context) - - [Sort](item-search/README.md#sort) diff --git a/fragments/filter/README.md b/fragments/filter/README.md index f8ca7f67..ef00eb46 100644 --- a/fragments/filter/README.md +++ b/fragments/filter/README.md @@ -4,17 +4,17 @@ - **Conformance Classes:** - Filter: - Item Search Filter: - - CQL2 Text: - - CQL2 JSON: - - Basic CQL2: + - CQL2 Text: + - CQL2 JSON: + - Basic CQL: - Advanced Comparison Operators: - Basic Spatial Operators: - Spatial Operators: - Temporal Operators: - - Custom Functions: - - Arithmetic Expressions: - - Array Operators: - - Property-Property Comparisons: + - Custom Functions: + - Arithmetic Expressions: + - Array Operators: + - Property-Property Comparisons: - **Extension [Maturity Classification](../../extensions.md#extension-maturity):** Pilot - **Dependents:** - [Item Search](../../item-search) @@ -30,26 +30,26 @@ - [Interaction with Endpoints](#interaction-with-endpoints) - [Examples](#examples) - [Example 1](#example-1) - - [Example 1: GET with cql2-text](#example-1-get-with-cql2-text) - - [Example 1: POST with cql2-json](#example-1-post-with-cql2-json) + - [Example 1: GET with cql-text](#example-1-get-with-cql-text) + - [Example 1: POST with cql-json](#example-1-post-with-cql-json) - [Example 2](#example-2) - - [Example 2: GET with cql2-text](#example-2-get-with-cql2-text) - - [Example 2: POST with cql2-json](#example-2-post-with-cql2-json) + - [Example 2: GET with cql-text](#example-2-get-with-cql-text) + - [Example 2: POST with cql-json](#example-2-post-with-cql-json) - [Example 3](#example-3) - - [Example 3: GET with cql2-text](#example-3-get-with-cql2-text) - - [Example 3: POST with cql2-json](#example-3-post-with-cql2-json) + - [Example 3: GET with cql-text](#example-3-get-with-cql-text) + - [Example 3: POST with cql-json](#example-3-post-with-cql-json) - [Example 4](#example-4) - - [Example 4: AND cql2-text (GET)](#example-4-and-cql2-text-get) - - [Example 4: AND cql2-json (POST)](#example-4-and-cql2-json-post) + - [Example 4: AND cql-text (GET)](#example-4-and-cql-text-get) + - [Example 4: AND cql-json (POST)](#example-4-and-cql-json-post) - [Example 5](#example-5) - - [Example 5: OR cql2-text (GET)](#example-5-or-cql2-text-get) - - [Example 5: OR cql2-json (POST)](#example-5-or-cql2-json-post) + - [Example 5: OR cql-text (GET)](#example-5-or-cql-text-get) + - [Example 5: OR cql-json (POST)](#example-5-or-cql-json-post) - [Example 6: Temporal](#example-6-temporal) - - [Example 6: ANYINTERACTS cql2-text (GET)](#example-6-anyinteracts-cql2-text-get) - - [Example 6: ANYINTERACTS cql2-json (POST)](#example-6-anyinteracts-cql2-json-post) + - [Example 6: ANYINTERACTS cql-text (GET)](#example-6-anyinteracts-cql-text-get) + - [Example 6: ANYINTERACTS cql-json (POST)](#example-6-anyinteracts-cql-json-post) - [Example 6: Spatial](#example-6-spatial) - - [Example 6: INTERSECTS cql2-text (GET)](#example-6-intersects-cql2-text-get) - - [Example 6: INTERSECTS cql2-json (POST)](#example-6-intersects-cql2-json-post) + - [Example 6: INTERSECTS cql-text (GET)](#example-6-intersects-cql-text-get) + - [Example 6: INTERSECTS cql-json (POST)](#example-6-intersects-cql-json-post) ## Overview @@ -63,8 +63,8 @@ last published [draft](https://portal.ogc.org/files/96288), so this spec referen major anticipated changes, so implementers are encouraged to move ahead with implementation, and to simply be aware that minor changes may need to be made in the future. -OAFeat Part 3 CQL2 formally defines the syntax of "CQL2" as both a text format (cql2-text) as an ABNF grammar -(largely similar to the BNF grammar in the General Model for CQL) and a JSON format (cql2-json) as a JSON Schema and +OAFeat Part 3 CQL2 formally defines the syntax of "CQL2" as both a text format (cql-text) as an ABNF grammar +(largely similar to the BNF grammar in the General Model for CQL) and a JSON format (cql-json) as a JSON Schema and OpenAPI schema, and provides a precise natural language description of the declarative semantics. The CQL Text format has long-standing use within geospatial software (e.g., GeoServer), is expected not to change before final. @@ -128,19 +128,19 @@ The implementation **must** support these conformance classes: - Filter (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:filter`) defines the Queryables mechanism and parameters `filter-lang`, `filter-crs`, and `filter`. -- Basic CQL2 (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:basic-cql2`) defines the basic operations allowed in +- Basic CQL (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:basic-cql`) defines the basic operations allowed in the query language used for the `filter` parameter defined by Filter. This includes logical operators (`AND`, `OR`, `NOT`), comparison operators (`=`, `<>`, `<`, `<=`, `>`, `>=`), and `IS NULL`. The comparison operators are allowed against string, numeric, boolean, and datetime types. - Item Search Filter (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:item-search-filter`) binds the Filter and - Basic CQL2 conformance classes to apply to the Item Search endpoint (`/search`). This class is the correlate of the OAFeat CQL Features - Filter class that binds Filter and Basic CQL2 to the Features resource (`/collections/{cid}/items`). + Basic CQL conformance classes to apply to the Item Search endpoint (`/search`). This class is the correlate of the OAFeat CQL Features + Filter class that binds Filter and Basic CQL to the Features resource (`/collections/{cid}/items`). The implementation **must** support at least one of the "CQL2 Text" or "CQL2 JSON" conformance classes that define the CQL format used in the filter parameter: -- CQL2 Text (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql2-text`) defines that the CQL2 Text format is supported by Item Search -- CQL JSON (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql2-json`) defines that the CQL JSON format is supported by Item Search +- CQL2 Text (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql-text`) defines that the CQL2 Text format is supported by Item Search +- CQL JSON (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql-json`) defines that the CQL JSON format is supported by Item Search If both are advertised as being supported, it is only required that both be supported for GET query parameters, and that only that CQL JSON be supported for POST JSON requests. It is recommended that clients use CQL2 Text in GET requests and @@ -158,16 +158,16 @@ For additional capabilities, the following classes can be implemented: - Temporal Operators (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:temporal-operators`) defines the same operators as OAF Part 3 CQL Enhanced Temporal Operators. -- Custom Functions (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:custom-functions`) defines the same operators as OAF Part 3 CQL Custom Functions. -- Arithmetic Expressions: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:arithmetic-expressions`) defines the same operators as OAF Part 3 CQL Arithmetic Expressions. -- Array Operators: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:array-operators`) defines the same operators as OAF Part 3 CQL Array Operators. -- Property-Property Comparisons: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:property-property-comparisons`) allows the +- Custom Functions (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:functions`) defines the same operators as OAF Part 3 CQL Custom Functions. +- Arithmetic Expressions: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:arithmetic`) defines the same operators as OAF Part 3 CQL Arithmetic Expressions. +- Array Operators: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:array-operators-operators`) defines the same operators as OAF Part 3 CQL Array Operators. +- Property-Property Comparisons: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:property-property`) allows the use of queryables (e.g., properties) in both positions of a clause, not just in the first position. This allows - predicates like `property1 == property2` be expressed, whereas the Basic CQL2 conformance class only requires + predicates like `property1 == property2` be expressed, whereas the Basic CQL conformance class only requires comparisons against literal values. Additionally, if an API implements the OGC API Features endpoint, it is **recommended** that the OAFeat Part 3 Filter, -Features Filter, and Basic CQL2 conformance classes be implemented, which allow use of CQL filters against the +Features Filter, and Basic CQL conformance classes be implemented, which allow use of CQL filters against the OAFeat Part 1 Features endpoint (`/collections/{collectionId}/items`). Note that POST with a JSON body to the Features resource is not supported, as POST is used by the [Transaction Extension](../../ogcapi-features/extensions/transaction/README.md) for creating items. @@ -175,7 +175,7 @@ to the Features resource is not supported, as POST is used by the ## Getting Started with Implementation It recommended that implementers start with fully implementing only a subset of functionality. A good place to start is -implementing only the Basic CQL2 conformance class of logical and comparison operators, defining a static Queryables +implementing only the Basic CQL conformance class of logical and comparison operators, defining a static Queryables schema with no queryables advertised, and only implementing CQL2 Text. Following from that can be support for INTERSECTS, defining a static Queryables schema with only the basic Item properties, and implementing CQL JSON. From there, other comparison operators can be implemented and a more @@ -183,8 +183,8 @@ dynamic Queryables schema. Formal definitions and grammars for CQL can be found here: -- The [OAFeat (CQL) spec](https://portal.ogc.org/files/96288) includes an ABNF for cql2-text and both JSON Schema and - OpenAPI specifications for cql2-json. The standalone files are: +- The [OAFeat (CQL) spec](https://portal.ogc.org/files/96288) includes an ABNF for cql-text and both JSON Schema and + OpenAPI specifications for cql-json. The standalone files are: - [cql.bnf](https://github.com/opengeospatial/ogcapi-features/blob/master/extensions/cql/standard/schema/cql.bnf) - [cql.json](https://github.com/opengeospatial/ogcapi-features/blob/master/extensions/cql/standard/schema/cql.json) - [cql.yml](https://github.com/opengeospatial/ogcapi-features/blob/master/extensions/cql/standard/schema/cql.yml) @@ -310,15 +310,15 @@ in STAC API by the Filter Extension. In this case, the queryables endpoint (`/qu This extension adds three GET query parameters or POST JSON fields to an Item Search request: -- filter-lang:`cql2-text` or `cql2-json`. If undefined, defaults to `cql2-text` for a GET request and `cql2-json` for a POST request. +- filter-lang:`cql-text` or `cql-json`. If undefined, defaults to `cql-text` for a GET request and `cql-json` for a POST request. - filter-crs: recommended to not be passed, but server must only accept `http://www.opengis.net/def/crs/OGC/1.3/CRS84` as a valid value, may reject any others - filter: CQL filter expression API implementations advertise which `filter-lang` values are supported via conformance classes in the Landing Page. At least one must be implemented, but it is recommended to implement both. If both are advertised as conformance classes, the -server should process either for a GET request, but may only process cql2-json for a POST request. If POST of cql2-text is not -supported, the server must return a 400 error if `filter-lang=cql2-text`. +server should process either for a GET request, but may only process cql-json for a POST request. If POST of cql-text is not +supported, the server must return a 400 error if `filter-lang=cql-text`. ## Interaction with Endpoints @@ -341,9 +341,9 @@ at least these values: "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:filter", "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:features-filter", - "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:basic-cql2", - "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql2-text", - "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql2-json", + "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:basic-cql", + "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql-text", + "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql-json", "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:basic-spatial-operators", "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:advanced-comparison-operators" @@ -439,18 +439,18 @@ in any of these examples. This example uses the queryables definition in (Interaction with Endpoints)(#interaction-with-endpoints). -#### Example 1: GET with cql2-text +#### Example 1: GET with cql-text -Note that `filter-lang` defaults to `cql2-text` in this case. The parameter `filter-crs` defaults +Note that `filter-lang` defaults to `cql-text` in this case. The parameter `filter-crs` defaults to `http://www.opengis.net/def/crs/OGC/1.3/CRS84` for a STAC API. ```javascript GET /search?filter=id='LC08_L1TP_060247_20180905_20180912_01_T1_L1TP' AND collection='landsat8_l1tp' ``` -#### Example 1: POST with cql2-json +#### Example 1: POST with cql-json -Note that `filter-lang` defaults to `cql2-json` in this case. The parameter `filter-crs` defaults +Note that `filter-lang` defaults to `cql-json` in this case. The parameter `filter-crs` defaults to `http://www.opengis.net/def/crs/OGC/1.3/CRS84` for a STAC API. ```javascript @@ -478,7 +478,7 @@ This example uses the queryables definition in [Interaction with Endpoints](#int Note that filtering on the `collection` field is relevant in Item Search, since the queries are cross-collection, whereas OGC API Features filters only operate against a single collection already. -#### Example 2: GET with cql2-text +#### Example 2: GET with cql-text ```javascript GET /search?filter=collection = 'landsat8_l1tp' @@ -489,12 +489,12 @@ GET /search?filter=collection = 'landsat8_l1tp' AND INTERSECTS(geometry, POLYGON((43.5845 -79.5442, 43.6079 -79.4893, 43.5677 -79.4632, 43.6129 -79.3925, 43.6223 -79.3238, 43.6576 -79.3163, 43.7945 -79.1178, 43.8144 -79.1542, 43.8555 -79.1714, 43.7509 -79.6390, 43.5845 -79.5442)) ``` -#### Example 2: POST with cql2-json +#### Example 2: POST with cql-json ```javascript POST /search { - "filter-lang": "cql2-json", + "filter-lang": "cql-json", "filter": { "and": [ "eq": [ @@ -567,18 +567,18 @@ This queryables JSON Schema is used in these examples: } ``` -#### Example 3: GET with cql2-text +#### Example 3: GET with cql-text ```javascript GET /search?filter=prop1 = prop2 ``` -#### Example 3: POST with cql2-json +#### Example 3: POST with cql-json ```javascript POST /search { - "filter-lang": "cql2-json", + "filter-lang": "cql-json", "filter": { "eq": [ { "property": "prop1" }, @@ -680,13 +680,13 @@ recording path intersection only a corner of a grid square. This examples shows Show me all imagery that has low cloud cover (less than 10), and high data coverage (50), as I'd like a cloud free image that is not just a tiny sliver of data. -#### Example 4: AND cql2-text (GET) +#### Example 4: AND cql-text (GET) ```javascript /search?filter=sentinel:data_coverage > 50 AND eo:cloud_cover < 10 ``` -#### Example 4: AND cql2-json (POST) +#### Example 4: AND cql-json (POST) ```json { @@ -720,13 +720,13 @@ coverage or low cloud cover. This uses the same queryables as Example 4. -#### Example 5: OR cql2-text (GET) +#### Example 5: OR cql-text (GET) ```javascript /search?filter=sentinel:data_coverage > 50 OR eo:cloud_cover < 10 ``` -#### Example 5: OR cql2-json (POST) +#### Example 5: OR cql-json (POST) ```json { @@ -756,13 +756,13 @@ This uses the same queryables as Example 4. The only temporal operator required is `ANYINTERACTS`. This is effectively that the datetime or interval operands have any overlap between them. -#### Example 6: ANYINTERACTS cql2-text (GET) +#### Example 6: ANYINTERACTS cql-text (GET) ```javascript /search?filter=datetime ANYINTERACTS 2020-11-11T00:00:00Z/2020-11-12T00:00:00Z ``` -#### Example 6: ANYINTERACTS cql2-json (POST) +#### Example 6: ANYINTERACTS cql-json (POST) ```json { @@ -778,16 +778,16 @@ have any overlap between them. ### Example 6: Spatial The only spatial operator that must be implemented is `INTERSECTS`. This has the same semantics as the one provided -in the Item Search `intersects` parameter. The `cql2-text` format uses WKT geometries and the `cql2-json` format uses +in the Item Search `intersects` parameter. The `cql-text` format uses WKT geometries and the `cql-json` format uses GeoJSON geometries. -#### Example 6: INTERSECTS cql2-text (GET) +#### Example 6: INTERSECTS cql-text (GET) ```javascript /search?filter=INTERSECTS(geometry,POLYGON((-77.0824 38.7886,-77.0189 38.7886,-77.0189 38.8351,-77.0824 38.8351,-77.0824 38.7886))) ``` -#### Example 6: INTERSECTS cql2-json (POST) +#### Example 6: INTERSECTS cql-json (POST) ```json { diff --git a/fragments/filter/openapi.yaml b/fragments/filter/openapi.yaml index 0636a1a9..be5fe32e 100644 --- a/fragments/filter/openapi.yaml +++ b/fragments/filter/openapi.yaml @@ -103,8 +103,8 @@ components: required: true schema: oneOf: - - $ref: '#/components/schemas/filter-cql2-json' - - $ref: '#/components/schemas/filter-cql2-text' + - $ref: '#/components/schemas/filter-cql-json' + - $ref: '#/components/schemas/filter-cql-text' filter-lang: name: filter-lang x-stac-api-fragment: filter @@ -112,7 +112,7 @@ components: description: |- **Extension:** Filter - The CQL filter encoding that the 'filter' value uses. Must be one of 'cql2-text' or 'cql2-json'. + The CQL filter encoding that the 'filter' value uses. Must be one of 'cql-text' or 'cql-json'. required: false schema: $ref: '#/components/schemas/filter-lang' @@ -138,24 +138,24 @@ components: A filter for properties in Items. properties: filter: - $ref: '#/components/schemas/filter-cql2-json' + $ref: '#/components/schemas/filter-cql-json' filter-lang: $ref: '#/components/schemas/filter-lang' filter-crs: $ref: '#/components/schemas/filter-crs' - filter-cql2-text: + filter-cql-text: description: | - A CQL filter expression in the 'cql2-text' encoding. + A CQL filter expression in the 'cql-text' encoding. type: string - filter-cql2-json: + filter-cql-json: $ref: './cql.yml#/components/schemas/booleanValueExpression' filter-lang: description: | The CQL filter encoding that the 'filter' value uses. type: string enum: - - 'cql2-text' - - 'cql2-json' + - 'cql-text' + - 'cql-json' filter-crs: description: | The coordinate reference system (CRS) used by spatial literals in the 'filter' value. The only value that STAC APIs must diff --git a/item-search/README.md b/item-search/README.md index d2065b70..8dcf2bf2 100644 --- a/item-search/README.md +++ b/item-search/README.md @@ -317,7 +317,7 @@ through the use of a `fields` parameter. The full description of how this extens The STAC search endpoint, `/search`, by default only accepts a limited set of parameters to limit the results by properties. The Filter extension adds a new parameter, `filter`, that can take a number of comparison operators to match predicates between the fields requested and the values of Item objects. It can be used with both GET and POST and supports two -query formats, `cql2-text` and `cql2-json`. The full details on the JSON structure are specified in the [filter +query formats, `cql-text` and `cql-json`. The full details on the JSON structure are specified in the [filter fragment](../fragments/filter/). ### Sort From 51194ce57d3a081cfbcda18afbf95b62ae7f5514 Mon Sep 17 00:00:00 2001 From: Phil Varner Date: Tue, 24 Aug 2021 09:47:03 -0400 Subject: [PATCH 04/14] lint --- fragments/filter/README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fragments/filter/README.md b/fragments/filter/README.md index ef00eb46..800fbb49 100644 --- a/fragments/filter/README.md +++ b/fragments/filter/README.md @@ -158,9 +158,12 @@ For additional capabilities, the following classes can be implemented: - Temporal Operators (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:temporal-operators`) defines the same operators as OAF Part 3 CQL Enhanced Temporal Operators. -- Custom Functions (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:functions`) defines the same operators as OAF Part 3 CQL Custom Functions. -- Arithmetic Expressions: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:arithmetic`) defines the same operators as OAF Part 3 CQL Arithmetic Expressions. -- Array Operators: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:array-operators-operators`) defines the same operators as OAF Part 3 CQL Array Operators. +- Custom Functions (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:functions`) defines the + same operators as OAF Part 3 CQL Custom Functions. +- Arithmetic Expressions: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:arithmetic`) defines + the same operators as OAF Part 3 CQL Arithmetic Expressions. +- Array Operators: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:array-operators-operators`) + defines the same operators as OAF Part 3 CQL Array Operators. - Property-Property Comparisons: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:property-property`) allows the use of queryables (e.g., properties) in both positions of a clause, not just in the first position. This allows predicates like `property1 == property2` be expressed, whereas the Basic CQL conformance class only requires From d3325cf972d581a7eb2acd56a54c2365476e47d7 Mon Sep 17 00:00:00 2001 From: Phil Varner Date: Tue, 24 Aug 2021 09:50:24 -0400 Subject: [PATCH 05/14] fix array-operators name --- extensions.md | 2 +- fragments/filter/README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions.md b/extensions.md index 6b32e648..a3365cf7 100644 --- a/extensions.md +++ b/extensions.md @@ -79,7 +79,7 @@ the service supports. This are listed at the top of each extension description, - - - - - + - - - [Context](item-search/README.md#context) - diff --git a/fragments/filter/README.md b/fragments/filter/README.md index 800fbb49..af347b3e 100644 --- a/fragments/filter/README.md +++ b/fragments/filter/README.md @@ -13,7 +13,7 @@ - Temporal Operators: - Custom Functions: - Arithmetic Expressions: - - Array Operators: + - Array Operators: - Property-Property Comparisons: - **Extension [Maturity Classification](../../extensions.md#extension-maturity):** Pilot - **Dependents:** @@ -162,7 +162,7 @@ For additional capabilities, the following classes can be implemented: same operators as OAF Part 3 CQL Custom Functions. - Arithmetic Expressions: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:arithmetic`) defines the same operators as OAF Part 3 CQL Arithmetic Expressions. -- Array Operators: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:array-operators-operators`) +- Array Operators: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:array-operators`) defines the same operators as OAF Part 3 CQL Array Operators. - Property-Property Comparisons: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:property-property`) allows the use of queryables (e.g., properties) in both positions of a clause, not just in the first position. This allows From 24c72a39e42a15ddb653722f560b8ad94a8aeb25 Mon Sep 17 00:00:00 2001 From: Phil Varner Date: Tue, 24 Aug 2021 09:52:27 -0400 Subject: [PATCH 06/14] rename CQL2 to CQL --- fragments/filter/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fragments/filter/README.md b/fragments/filter/README.md index af347b3e..748dfb02 100644 --- a/fragments/filter/README.md +++ b/fragments/filter/README.md @@ -4,8 +4,8 @@ - **Conformance Classes:** - Filter: - Item Search Filter: - - CQL2 Text: - - CQL2 JSON: + - CQL Text: + - CQL JSON: - Basic CQL: - Advanced Comparison Operators: - Basic Spatial Operators: @@ -136,14 +136,14 @@ The implementation **must** support these conformance classes: Basic CQL conformance classes to apply to the Item Search endpoint (`/search`). This class is the correlate of the OAFeat CQL Features Filter class that binds Filter and Basic CQL to the Features resource (`/collections/{cid}/items`). -The implementation **must** support at least one of the "CQL2 Text" or "CQL2 JSON" conformance classes that define +The implementation **must** support at least one of the "CQL Text" or "CQL JSON" conformance classes that define the CQL format used in the filter parameter: -- CQL2 Text (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql-text`) defines that the CQL2 Text format is supported by Item Search +- CQL Text (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql-text`) defines that the CQL Text format is supported by Item Search - CQL JSON (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql-json`) defines that the CQL JSON format is supported by Item Search If both are advertised as being supported, it is only required that both be supported for GET query parameters, and that -only that CQL JSON be supported for POST JSON requests. It is recommended that clients use CQL2 Text in GET requests and +only that CQL JSON be supported for POST JSON requests. It is recommended that clients use CQL Text in GET requests and CQL JSON in POST requests. For additional capabilities, the following classes can be implemented: @@ -179,7 +179,7 @@ to the Features resource is not supported, as POST is used by the It recommended that implementers start with fully implementing only a subset of functionality. A good place to start is implementing only the Basic CQL conformance class of logical and comparison operators, defining a static Queryables -schema with no queryables advertised, and only implementing CQL2 Text. Following from that can be support for +schema with no queryables advertised, and only implementing CQL Text. Following from that can be support for INTERSECTS, defining a static Queryables schema with only the basic Item properties, and implementing CQL JSON. From there, other comparison operators can be implemented and a more dynamic Queryables schema. From a80c1dfa87307180ec2a0527b4b115a81e646d70 Mon Sep 17 00:00:00 2001 From: Phil Varner Date: Tue, 24 Aug 2021 09:54:11 -0400 Subject: [PATCH 07/14] wording --- fragments/filter/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fragments/filter/README.md b/fragments/filter/README.md index 748dfb02..815a45ae 100644 --- a/fragments/filter/README.md +++ b/fragments/filter/README.md @@ -119,8 +119,8 @@ implementing functionality they do not need or may not be able to implement func their underlying datastore, e.g., Elasticsearch does not support the spatial predicates required by the Spatial Operators conformance class, only the `intersects` operator in the Basic Spatial Operators class. -The precise decomposition of the OAFeat conformance classes is still a work in progress, but rapidly being finalized -(see [ogcapi-features/issues/579](https://github.com/opengeospatial/ogcapi-features/issues/579)). +The precise decomposition of the OAFeat conformance classes is still a work in progress, but is being finalized +rapidly (see [ogcapi-features/issues/579](https://github.com/opengeospatial/ogcapi-features/issues/579)). The STAC API Filter Extension reuses the definitions and conformance classes in OAFeat CQL, with a single minor exception described below. This extension uses conformance classes with a prefix of `https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:`. From 1ff367becc1b34391f419ec8dacb1970718b22c5 Mon Sep 17 00:00:00 2001 From: Phil Varner Date: Mon, 30 Aug 2021 12:58:43 -0400 Subject: [PATCH 08/14] update adv comp ops and queryables to anticipated OAFeat changes --- fragments/filter/README.md | 42 +++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/fragments/filter/README.md b/fragments/filter/README.md index 815a45ae..3cc43de4 100644 --- a/fragments/filter/README.md +++ b/fragments/filter/README.md @@ -149,8 +149,9 @@ CQL JSON in POST requests. For additional capabilities, the following classes can be implemented: - Advanced Comparison Operators (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:advanced-comparison-operators`) defines the `LIKE`, - `BETWEEN`, and `IN` operators. This conformance class in Filter Extension does **not** require implementing `lower` and - `upper` functions as the OAFeat CQL conformance class requires. + `BETWEEN`, and `IN` operators. Note: this conformance class does **not** require implementing the + `lower` and `upper` functions as defined in the latest OAFeat CQL spec, as these will soon be + removed from the corresponding OAFeat CQL conformance class. - Basic Spatial Operators (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:basic-spatial-operators`) defines the `INTERSECTS` predicate. - Spatial Operators (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:spatial-operators`) defines the @@ -179,7 +180,8 @@ to the Features resource is not supported, as POST is used by the It recommended that implementers start with fully implementing only a subset of functionality. A good place to start is implementing only the Basic CQL conformance class of logical and comparison operators, defining a static Queryables -schema with no queryables advertised, and only implementing CQL Text. Following from that can be support for +schema with no queryables advertised and the `additionalProperties` field set to `true`, and +only implementing CQL Text. Following from that can be support for INTERSECTS, defining a static Queryables schema with only the basic Item properties, and implementing CQL JSON. From there, other comparison operators can be implemented and a more dynamic Queryables schema. @@ -214,16 +216,15 @@ not compliant with this extension. ## Queryables -The Queryables mechanism allows a client to discover what variable terms are available for use when writing filter -expressions. These variables can be defined per-collection, and the intersection of these variables over all collections is what -is available for filtering when there are no collection restrictions. These queryables are the only variables that may be used -in filter expressions, and if any variable is used in expression that is not defined as a queryable and error should be +The Queryables mechanism allows a client to discover what terms are available for use when writing filter +expressions. These terms can be defined per-collection, and the intersection of these terms over all collections is what +is available for filtering when there are no collection restrictions. By default, these queryables are the only terms that may be used +in filter expressions, and if any term is used in expression that is not defined as a queryable and error should be returned according to OAFeat Part 3. It is recognized that this is a severe restriction in STAC APIs that have highly variable -and dynamic content. It is possible that this will change in the OAFeat Part 3 spec, see -this [issue](https://github.com/opengeospatial/ogcapi-features/issues/582). For now, implementers may choose to allow -fully-qualified property -names not advertised in queryables (e.g., `properties.eo:cloud_cover`, in anticipation that there be some -mechanism to explicitly allow or advertise this in the future. +and dynamic content, so this behavior may be modified by setting the `additionalProperties` attribute in the +queryables definition to `true`. As such, any syntactically-valid term for a property will be accepted, and the +matching semantics are such that, if an Item does not have an attribute by that name, the value is assumed to be +`null`. It is recommended to use fully-qualified property names (e.g., `properties.eo:cloud_cover`). Queryables are advertised via a JSON Schema document retrieved from the `/queryables` endpoint. This endpoint at the root retrieves queryables that apply to all collections. When used as a subresource of the collection resource @@ -257,7 +258,8 @@ definitions for STAC Items should include at least the fields id, collection, ge "description" : "Datetime", "$ref": "https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/datetime.json#/properties/datetime" } - } + }, + "additionalProperties": true } ``` @@ -271,11 +273,11 @@ The Landing Page endpoint (`/`) will have a Link with rel `http://www.opengis.ne the endpoint `/queryables`. Additionally, each Collection resource will have a Link to the queryables resource for that collection, e.g., `/collections/collection1/queryables`. -The queryables endpoint returns a JSON Schema describing the names and types variables that may be used in filter expressions. +The queryables endpoint returns a JSON Schema describing the names and types of terms that may be used in filter expressions. This response is defined in JSON Schema because it is a well-specified typed schema, but it is not used for validating a JSON -document derived from it. This schema defines the variables that may be used in a CQL filter. +document derived from it. This schema defines the terms that may be used in a CQL filter. -These queryable variables are mapped by the service to filter Items. For example, the service may define a queryable with the +These queryable terms are mapped by the service to filter Items. For example, the service may define a queryable with the name "eo:cloud_cover" that can be used in a CQL expression like `eo:cloud_cover <= 10`, with the semantics that only Items where the `properties.eo:cloud_cover` value was <= 10 would match the filter. The server would then translate this into an appropriate query for the data within its datastore. @@ -283,7 +285,7 @@ query for the data within its datastore. Queryables can be static or dynamically derived. For example, `cloud_cover` might be specified to have a value 0 to 100 or a field may have a set of enumerated values dynamically determined by an aggreation at runtime. This schema can be used by a UI or interactive client to dynamically expose to the user the fields that are available for filtering, and provide a precise group -of options for the values of these variables. +of options for the values of these terms. Queryables can also be used to advertise synthesized property values. The only requirement in CQL is that the property have a type and evaluate to literal value of that type or NULL. For example, a filter like "Items must have an Asset with an eo:band with @@ -305,7 +307,8 @@ in STAC API by the Filter Extension. In this case, the queryables endpoint (`/qu "title" : "Queryables for Example STAC API", "description" : "Queryable names for the example STAC API Item Search filter.", "properties" : { - } + }, + "additionalProperties": true } ``` @@ -410,7 +413,8 @@ The Queryables endpoint (`/queryables`) returns something like the following: "description" : "Asset eo:bands common names", "$ref": "https://stac-extensions.github.io/eo/v1.0.0/schema.json#/properties/eo:bands/common_name" } - } + }, + "additionalProperties": true } ``` From 7f0d339ecd553c70bafc2a9e0c3e6ff497f60e5a Mon Sep 17 00:00:00 2001 From: Phil Varner Date: Tue, 7 Sep 2021 13:08:57 -0400 Subject: [PATCH 09/14] use OAFeat conformance class URIs --- CHANGELOG.md | 2 +- extensions.md | 24 ++++++------- fragments/filter/README.md | 72 ++++++++++++++++++++------------------ 3 files changed, 50 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01b60644..0d656014 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Filter Extension - query language is now referred to as "CQL2" rather than CQL +- Filter Extension now uses OAFeat Part 3 conformance class URIs - Filter Extension - The following changes have been made to the Filter Extension conformance classes to align with changes to the OAFeat CQL draft. All classes whose names have changed also have changed conformance URI strings. - "Basic CQL" now includes the "not equal" operator (`<>`) @@ -24,7 +25,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - "Arithmetic" has been renamed "Arithmetic Expressions" - "Arrays" has been renamed "Array Operators" - "Queryable Second Operand" has been renamed "Property-Property Comparisons" - ### Deprecated ### Removed diff --git a/extensions.md b/extensions.md index a3365cf7..e7369964 100644 --- a/extensions.md +++ b/extensions.md @@ -68,19 +68,19 @@ the service supports. This are listed at the top of each extension description, - [Fields](item-search/README.md#fields) - - [Filter](item-search/README.md#filter) - - - - + - + - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - - [Context](item-search/README.md#context) - - [Sort](item-search/README.md#sort) diff --git a/fragments/filter/README.md b/fragments/filter/README.md index 3b9598b6..f585506a 100644 --- a/fragments/filter/README.md +++ b/fragments/filter/README.md @@ -2,19 +2,19 @@ - **OpenAPI specification:** [openapi.yaml](openapi.yaml) - **Conformance Classes:** - - Filter: + - Filter: - Item Search Filter: - - CQL Text: - - CQL JSON: - - Basic CQL: - - Advanced Comparison Operators: - - Basic Spatial Operators: - - Spatial Operators: - - Temporal Operators: - - Custom Functions: - - Arithmetic Expressions: - - Array Operators: - - Property-Property Comparisons: + - CQL Text: + - CQL JSON: + - Basic CQL: + - Advanced Comparison Operators: + - Basic Spatial Operators: + - Spatial Operators: + - Temporal Operators: + - Custom Functions: + - Arithmetic Expressions: + - Array Operators: + - Property-Property Comparisons: - **Extension [Maturity Classification](../../extensions.md#extension-maturity):** Pilot - **Dependents:** - [Item Search](../../item-search) @@ -112,7 +112,7 @@ CQL enables more expressive queries than supported by STAC API Item Search. Thes ## Conformance Classes -OAFeat CQL defines several conformance classes that allow implementers to create compositions of +OAFeat Part 3 CQL defines several conformance classes that allow implementers to create compositions of functionality that support whatever expressiveness they need. This allows implementers to incrementally support CQL syntax, without needing to implement a huge spec all at once. Some implementers choose not to incur the cost of implementing functionality they do not need or may not be able to implement functionality that is not supported by @@ -121,14 +121,16 @@ Spatial Operators conformance class, only the `intersects` operator in the Basic The precise decomposition of the OAFeat conformance classes is still a work in progress, but is being finalized rapidly (see [ogcapi-features/issues/579](https://github.com/opengeospatial/ogcapi-features/issues/579)). -The STAC API Filter Extension reuses the definitions and conformance classes in OAFeat CQL, with a single minor exception -described below. This extension uses conformance classes with a prefix of `https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:`. +The STAC API Filter Extension reuses the definitions and conformance classes in OAFeat CQL, +adding only the Item Search Filter conformance class +(`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:item-search-filter`) to bind +the CQL filter behavior to the Item Search resource. The implementation **must** support these conformance classes: -- Filter (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:filter`) defines the Queryables mechanism and +- Filter (`http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/filter`) defines the Queryables mechanism and parameters `filter-lang`, `filter-crs`, and `filter`. -- Basic CQL (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:basic-cql`) defines the basic operations allowed in +- Basic CQL (`http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/basic-cql`) defines the basic operations allowed in the query language used for the `filter` parameter defined by Filter. This includes logical operators (`AND`, `OR`, `NOT`), comparison operators (`=`, `<>`, `<`, `<=`, `>`, `>=`), and `IS NULL`. The comparison operators are allowed against string, numeric, boolean, and datetime types. @@ -139,8 +141,8 @@ The implementation **must** support these conformance classes: The implementation **must** support at least one of the "CQL Text" or "CQL JSON" conformance classes that define the CQL format used in the filter parameter: -- CQL Text (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql-text`) defines that the CQL Text format is supported by Item Search -- CQL JSON (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql-json`) defines that the CQL JSON format is supported by Item Search +- CQL Text (`http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/cql-text`) defines that the CQL Text format is supported by Item Search +- CQL JSON (`http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/cql-json`) defines that the CQL JSON format is supported by Item Search If both are advertised as being supported, it is only required that both be supported for GET query parameters, and that only that CQL JSON be supported for POST JSON requests. It is recommended that clients use CQL Text in GET requests and @@ -148,24 +150,24 @@ CQL JSON in POST requests. For additional capabilities, the following classes can be implemented: - Advanced Comparison Operators - (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:advanced-comparison-operators`) defines the `LIKE`, + (`http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/advanced-comparison-operators`) defines the `LIKE`, `BETWEEN`, and `IN` operators. Note: this conformance class does **not** require implementing the `lower` and `upper` functions as defined in the latest OAFeat CQL spec, as these will soon be removed from the corresponding OAFeat CQL conformance class. -- Basic Spatial Operators (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:basic-spatial-operators`) defines the `INTERSECTS` predicate. +- Basic Spatial Operators (`http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/basic-spatial-operators`) defines the `INTERSECTS` predicate. - Spatial Operators - (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:spatial-operators`) defines the + (`http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/spatial-operators`) defines the same operators as OAF Part 3 CQL Advanced Spatial Operators. - Temporal Operators - (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:temporal-operators`) defines the + (`http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/temporal-operators`) defines the same operators as OAF Part 3 CQL Enhanced Temporal Operators. -- Custom Functions (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:functions`) defines the +- Custom Functions (`http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/functions`) defines the same operators as OAF Part 3 CQL Custom Functions. -- Arithmetic Expressions: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:arithmetic`) defines +- Arithmetic Expressions: (`http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/arithmetic`) defines the same operators as OAF Part 3 CQL Arithmetic Expressions. -- Array Operators: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:array-operators`) +- Array Operators: (`http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/array-operators`) defines the same operators as OAF Part 3 CQL Array Operators. -- Property-Property Comparisons: (`https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:property-property`) allows the +- Property-Property Comparisons: (`http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/property-property`) allows the use of queryables (e.g., properties) in both positions of a clause, not just in the first position. This allows predicates like `property1 == property2` be expressed, whereas the Basic CQL conformance class only requires comparisons against literal values. @@ -339,19 +341,19 @@ at least these values: "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/oas30", "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/geojson", - "http://www.opengis.net/spec/ogcapi_common-2/1.0/req/collections", + "http://www.opengis.net/spec/ogcapi_common-2/1.0/conf/collections", "http://api.stacspec.org/v1.0.0-beta.4/core", "http://api.stacspec.org/v1.0.0-beta.4/stac-search", "http://api.stacspec.org/v1.0.0-beta.4/stac-response", - "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:filter", - "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:features-filter", - "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:basic-cql", - "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql-text", - "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:cql-json", - "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:basic-spatial-operators", - "https://api.stacspec.org/v1.0.0-beta.4/item-search#filter:advanced-comparison-operators" + "http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/filter", + "http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/features-filter", + "http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/basic-cql", + "http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/cql-text", + "http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/cql-json", + "http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/basic-spatial-operators", + "http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/advanced-comparison-operators" ], "links": [ From ee366f1f219b2dbf32b74037b84e3587bc2863a9 Mon Sep 17 00:00:00 2001 From: Phil Varner Date: Wed, 8 Sep 2021 11:31:09 -0400 Subject: [PATCH 10/14] add more complex filter examples, cleanup linting errors --- collections/README.md | 15 +-- core/README.md | 3 +- fragments/filter/README.md | 230 ++++++++++++++++++++++--------------- implementation.md | 3 +- 4 files changed, 147 insertions(+), 104 deletions(-) diff --git a/collections/README.md b/collections/README.md index 22afb8eb..7fe35cf9 100644 --- a/collections/README.md +++ b/collections/README.md @@ -1,10 +1,10 @@ # STAC API - Collections - [STAC API - Collections](#stac-api---collections) - - [Link Relations](#link-relations) - - [Endpoints](#endpoints) - - [Example](#example) - - [Conformance](#conformance) + - [Link Relations](#link-relations) + - [Endpoints](#endpoints) + - [Example](#example) + - [Conformance](#conformance) - **OpenAPI specification:** Missing - **Conformance URI:** @@ -32,15 +32,16 @@ The following Link relations shall exist in the Landing Page (root). | `service-desc` | `/api` (recommended) | OAFeat OpenAPI | The OpenAPI service description. Uses the `application/vnd.oai.openapi+json;version=3.0` media type to refer to the OpenAPI 3.0 document that defines the service's API | | `data` | `/collections` | OAFeat | List of Collections | A `service-doc` endpoint is recommended, but not required. + | **rel** | **href** | **From** | **Description** | | ------------- | ------------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------- | | `service-doc` | `/api.html` (recommended) | OAFeat OpenAPI | An HTML service description. Uses the `text/html` media type to refer to a human-consumable description of the service | Additionally, `child` relations may exist to individual catalogs and collections. -| **rel** | **href** | **From** | **Description** | -| -------------- | -------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `child` | various | STAC Core | The child STAC Catalogs & Collections. Provides curated paths to get to STAC Collection and Item objects | +| **rel** | **href** | **From** | **Description** | +| -------------- | -------------------- | -------------- | --------------- | +| `child` | various | STAC Core | The child STAC Catalogs & Collections. Provides curated paths to get to STAC Collection and Item objects | The following Link relations should exist in the `/collections` endpoint response. diff --git a/core/README.md b/core/README.md index 4a6edd00..b3fc2571 100644 --- a/core/README.md +++ b/core/README.md @@ -57,16 +57,17 @@ The following Link relations shall exist in the Landing Page (root). | `service-desc` | `/api` (recommended) | OAFeat OpenAPI | The OpenAPI service description. Uses the `application/vnd.oai.openapi+json;version=3.0` media type to refer to the OpenAPI 3.0 document that defines the service's API | A `service-doc` endpoint is recommended, but not required. + | **rel** | **href** | **From** | **Description** | | ------------- | ------------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------- | | `service-doc` | `/api.html` (recommended) | OAFeat OpenAPI | An HTML service description. Uses the `text/html` media type to refer to a human-consumable description of the service | Additionally, `child` relations may exist to individual catalogs and collections. + | **rel** | **href** | **From** | **Description** | | -------------- | -------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `child` | various | STAC Core | The child STAC Catalogs & Collections. Provides curated paths to get to STAC Collection and Item objects | - It is also valid to have `item` links from the landing page, but most STAC API services are used to serve up a large number of features, so they typically use several layers of intermediate `child` links before getting to Item objects. Note that the `items` (plural) diff --git a/fragments/filter/README.md b/fragments/filter/README.md index f585506a..28a5a967 100644 --- a/fragments/filter/README.md +++ b/fragments/filter/README.md @@ -47,9 +47,15 @@ - [Example 6: Temporal](#example-6-temporal) - [Example 6: ANYINTERACTS cql-text (GET)](#example-6-anyinteracts-cql-text-get) - [Example 6: ANYINTERACTS cql-json (POST)](#example-6-anyinteracts-cql-json-post) - - [Example 6: Spatial](#example-6-spatial) - - [Example 6: INTERSECTS cql-text (GET)](#example-6-intersects-cql-text-get) - - [Example 6: INTERSECTS cql-json (POST)](#example-6-intersects-cql-json-post) + - [Example 7: Spatial](#example-7-spatial) + - [Example 7: INTERSECTS cql-text (GET)](#example-7-intersects-cql-text-get) + - [Example 7: INTERSECTS cql-json (POST)](#example-7-intersects-cql-json-post) + - [Example 8: Spatial Disjunction](#example-8-spatial-disjunction) + - [Example 8: INTERSECTS cql-text (GET)](#example-8-intersects-cql-text-get) + - [Example 8: INTERSECTS cql-json (POST)](#example-8-intersects-cql-json-post) + - [Example 9: Using IS NULL](#example-9-using-is-null) + - [Example 9: cql-text (GET)](#example-9-cql-text-get) + - [Example 9: cql-json (POST)](#example-9-cql-json-post) ## Overview @@ -467,20 +473,9 @@ to `http://www.opengis.net/def/crs/OGC/1.3/CRS84` for a STAC API. POST /search { "filter": { - "and": [{ - "eq": [{ - "property": "id" - }, - "LC08_L1TP_060247_20180905_20180912_01_T1_L1TP" - ] - }, - { - "eq": [{ - "property": "collection" - }, - "landsat8_l1tp" - ] - } + "and": [ + { "eq": [ { "property": "id" }, "LC08_L1TP_060247_20180905_20180912_01_T1_L1TP" ] }, + { "eq": [ { "property": "collection" }, "landsat8_l1tp" ] } ] } } @@ -511,29 +506,13 @@ POST /search { "filter-lang": "cql-json", "filter": { - "and": [{ - "eq": [{ - "property": "collection" - }, - "landsat8_l1tp" - ] - }, - { - "lte": [{ - "property": "eo:cloud_cover" - }, - "10" - ] - }, - { - "gte": [{ - "property": "datetime" - }, - "2021-04-08T04:39:23Z" - ] - }, + "and": [ + { "eq": [ { "property": "collection" }, "landsat8_l1tp" ] }, + { "lte": [ { "property": "eo:cloud_cover" }, "10" ] }, + { "gte": [ { "property": "datetime" }, "2021-04-08T04:39:23Z" ] }, { - "intersects": [{ + "intersects": [ + { "property": "geometry" }, { @@ -712,26 +691,13 @@ a tiny sliver of data. ```json { - "filter": { - "and": [ - { - "gt": [ - { - "property": "sentinel:data_coverage" - }, - 50 - ] - }, - { - "lt": [ - { - "property": "eo:cloud_cover" - }, - 10 - ] - } - ] - } + "filter-lang": "cql-json", + "filter": { + "and": [ + { "gt": [ { "property": "sentinel:data_coverage" }, 50 ] }, + { "lt": [ { "property": "eo:cloud_cover" }, 10 ] } + ] + } } ``` @@ -752,22 +718,13 @@ This uses the same queryables as Example 4. ```json { + "filter-lang": "cql-json", "filter": { "or": [ - { - "gt": [ - { "property": "sentinel:data_coverage" }, - 50 - ] - }, - { - "lt": [ - { "property": "eo:cloud_cover" }, - 10 - ] - } - ] - } + { "gt": [ { "property": "sentinel:data_coverage" }, 50 ] }, + { "lt": [ { "property": "eo:cloud_cover" }, 10 ] } + ] + } } ``` @@ -788,43 +745,126 @@ have any overlap between them. ```json { + "filter-lang": "cql-json", "filter": { - "anyinteracts": [ - { "property": "datetime" }, - [ "2020-11-11T00:00:00Z", "2020-11-12T00:00:00Z"] - ] + "anyinteracts": [ + { "property": "datetime" }, + [ "2020-11-11T00:00:00Z", "2020-11-12T00:00:00Z"] + ] } } ``` -### Example 6: Spatial +### Example 7: Spatial -The only spatial operator that must be implemented is `INTERSECTS`. This has the same semantics as the one provided -in the Item Search `intersects` parameter. The `cql-text` format uses WKT geometries and the `cql-json` format uses -GeoJSON geometries. +The only spatial operator that must be implemented for Basic Spatial Operators +is `INTERSECTS`. This has the same semantics as the one provided +in the Item Search `intersects` parameter. The `cql-text` format uses WKT geometries and the `cql-json` +format uses GeoJSON geometries. -#### Example 6: INTERSECTS cql-text (GET) +#### Example 7: INTERSECTS cql-text (GET) ```javascript /search?filter=INTERSECTS(geometry,POLYGON((-77.0824 38.7886,-77.0189 38.7886,-77.0189 38.8351,-77.0824 38.8351,-77.0824 38.7886))) ``` -#### Example 6: INTERSECTS cql-json (POST) +#### Example 7: INTERSECTS cql-json (POST) ```json { - "filter": { - "intersects": [ - { "property": "geometry" } , - { - "type": "Polygon", - "coordinates": [[ - [-77.0824, 38.7886], [-77.0189, 38.7886], - [-77.0189, 38.8351], [-77.0824, 38.8351], - [-77.0824, 38.7886] - ]] - } + "filter-lang": "cql-json", + "filter": { + "intersects": [ + { "property": "geometry" } , + { + "type": "Polygon", + "coordinates": [[ + [-77.0824, 38.7886], [-77.0189, 38.7886], + [-77.0189, 38.8351], [-77.0824, 38.8351], + [-77.0824, 38.7886] + ]] + } + ] + } +} +``` + +### Example 8: Spatial Disjunction + +One limitation of the `intersects` parameter is that only a single geometry may be provided. While most +GeoJSON geometries can be combined to form a composite (e.g., multiple Polygons can be combined to form a +MultiPolygon), this is much easier to do in the query by combining `INTERSECTS` predicates with the `OR` +logical operator. + +#### Example 8: INTERSECTS cql-text (GET) + +```javascript +/search?filter=INTERSECTS(geometry,POLYGON((-77.0824 38.7886,-77.0189 38.7886,-77.0189 38.8351,-77.0824 38.8351,-77.0824 38.7886))) OR INTERSECTS(geometry,POLYGON((-79.0935 38.7886,-79.0290 38.7886,-79.0290 38.8351,-79.0935 38.8351,-79.0935 38.7886))) +``` + +#### Example 8: INTERSECTS cql-json (POST) + +```json +{ + "filter": { + "or" : [ + "intersects": [ + { "property": "geometry" } , + { + "type": "Polygon", + "coordinates": [[ + [-77.0824, 38.7886], [-77.0189, 38.7886], + [-77.0189, 38.8351], [-77.0824, 38.8351], + [-77.0824, 38.7886] + ]] + } + ], + "intersects": [ + { "property": "geometry" } , + { + "type": "Polygon", + "coordinates": [[ + [-79.0935, 38.7886], [-79.0290, 38.7886], + [-79.0290, 38.8351], [-79.0935, 38.8351], + [-79.0935, 38.7886] + ]] + } + ] + ] + } +} +``` + +### Example 9: Using IS NULL + +One of the main use cases for STAC API is doing cross-collection query. Commonly, this means that items have +different sets of properties. For example, a collection of Sentinel 2 data may have a property +`sentinel:data_coverage` and a collection of Landsat 8 data may have a corresponding property +`landsat:coverage_percent`, both representing what percentage of a given gridded scene actually contains +data. However, we many also want to also include in our result items that do not have a value defined for +either of those properties. + +#### Example 9: cql-text (GET) + +```javascript +/search?filter=sentinel:data_coverage > 50 OR landsat:coverage_percent < 10 OR (sentinel:data_coverage IS NULL AND landsat:coverage_percent IS NULL) +``` + +#### Example 9: cql-json (POST) + +```json +{ + "filter": { + "or": [ + { "gte": [ { "property": "sentinel:data_coverage" }, 50 ] }, + { "gte": [ { "property": "landsat:coverage_percent" }, 50 ] }, + { + "and": [ + { "isNull": { "property": "sentinel:data_coverage" } }, + { "isNull": { "property": "landsat:coverage_percent" } } ] - }, + } + ] + } } ``` diff --git a/implementation.md b/implementation.md index eb335b04..4f4a2e34 100644 --- a/implementation.md +++ b/implementation.md @@ -70,7 +70,8 @@ RFC 3339 datetime or an interval) is: language standard libraries do not parse ISO8601 datetimes correctly, for example, the built-in Python datetime library does not handle `Z` as a timezone. -Below are a few examples of valid RFC 3339 datetimes. Note the uses of fractional seconds, the use of `.` as the fractional seconds separator, Z or z as a timezone, +Below are a few examples of valid RFC 3339 datetimes. Note the uses of fractional seconds, the use of `.` +as the fractional seconds separator, Z or z as a timezone, positive and negative arbitrary offset timezones, and T or t as a separator between date and time. While the RFC 3339 spec does not define the required number of fractional seconds, STAC API only requires up to 9 digits be supported. From e9de6d8216e7478d4e29d946c8ed44ee3be83f93 Mon Sep 17 00:00:00 2001 From: Phil Varner Date: Tue, 5 Oct 2021 11:45:20 -0400 Subject: [PATCH 11/14] Update implementation.md Co-authored-by: Matthias Mohr --- implementation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/implementation.md b/implementation.md index 4f4a2e34..9a3e72c9 100644 --- a/implementation.md +++ b/implementation.md @@ -71,7 +71,7 @@ RFC 3339 datetime or an interval) is: Python datetime library does not handle `Z` as a timezone. Below are a few examples of valid RFC 3339 datetimes. Note the uses of fractional seconds, the use of `.` -as the fractional seconds separator, Z or z as a timezone, +as the fractional seconds separator, Z (recommended) or z as a timezone, positive and negative arbitrary offset timezones, and T or t as a separator between date and time. While the RFC 3339 spec does not define the required number of fractional seconds, STAC API only requires up to 9 digits be supported. From d5b0084f5e31bccf6585d9e9520deccafc289a5c Mon Sep 17 00:00:00 2001 From: Phil Varner Date: Tue, 5 Oct 2021 11:45:33 -0400 Subject: [PATCH 12/14] Update implementation.md Co-authored-by: Matthias Mohr --- implementation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/implementation.md b/implementation.md index 9a3e72c9..2b61cd75 100644 --- a/implementation.md +++ b/implementation.md @@ -72,7 +72,7 @@ RFC 3339 datetime or an interval) is: Below are a few examples of valid RFC 3339 datetimes. Note the uses of fractional seconds, the use of `.` as the fractional seconds separator, Z (recommended) or z as a timezone, -positive and negative arbitrary offset timezones, and T or t as a separator between date and time. While +positive and negative arbitrary offset timezones, and T (recommended) or t as a separator between date and time. While the RFC 3339 spec does not define the required number of fractional seconds, STAC API only requires up to 9 digits be supported. From 056abfc28a0bdbfea4b0056e0e4b6e6eaee74e63 Mon Sep 17 00:00:00 2001 From: Phil Varner Date: Tue, 5 Oct 2021 12:04:43 -0400 Subject: [PATCH 13/14] minor changes to examples --- fragments/filter/README.md | 56 +++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/fragments/filter/README.md b/fragments/filter/README.md index 28a5a967..080e287a 100644 --- a/fragments/filter/README.md +++ b/fragments/filter/README.md @@ -291,11 +291,11 @@ name "eo:cloud_cover" that can be used in a CQL expression like `eo:cloud_cover query for the data within its datastore. Queryables can be static or dynamically derived. For example, `cloud_cover` might be specified to have a value 0 to 100 or a field -may have a set of enumerated values dynamically determined by an aggreation at runtime. This schema can be used by a UI or +may have a set of enumerated values dynamically determined by an aggregation at runtime. This schema can be used by a UI or interactive client to dynamically expose to the user the fields that are available for filtering, and provide a precise group of options for the values of these terms. -Queryables can also be used to advertise synthesized property values. The only requirement in CQL is that the property have a type +Queryables can also be used to advertise "synthesized" property values. The only requirement in CQL is that the property have a type and evaluate to literal value of that type or NULL. For example, a filter like "Items must have an Asset with an eo:band with the common_name of 'nir'" can be expressed. A Queryable `assets_bands` could be defined to have a type of array of string and have the semantics that it contains all of `common_name` values across all assets and bands for an Item. This could then be @@ -446,10 +446,13 @@ These parameters/fields must be supported by the STAC Item Search endpoint and O ## Examples -Note: the GET examples with query parameters are unescaped to make them easier to read. +Note: the GET examples with query parameters are unescaped to make them easier to read. + +The GET examples are assuming a call to `GET /search` and the POST examples are assuming a +call to `POST /search`. The parameter `filter-crs` always defaults to `http://www.opengis.net/def/crs/OGC/1.3/CRS84` for a STAC API, so is not shown -in any of these examples. +in any of these examples. ### Example 1 @@ -460,8 +463,8 @@ This example uses the queryables definition in (Interaction with Endpoints)(#int Note that `filter-lang` defaults to `cql-text` in this case. The parameter `filter-crs` defaults to `http://www.opengis.net/def/crs/OGC/1.3/CRS84` for a STAC API. -```javascript -GET /search?filter=id='LC08_L1TP_060247_20180905_20180912_01_T1_L1TP' AND collection='landsat8_l1tp' +``` +filter=id='LC08_L1TP_060247_20180905_20180912_01_T1_L1TP' AND collection='landsat8_l1tp' ``` #### Example 1: POST with cql-json @@ -469,8 +472,7 @@ GET /search?filter=id='LC08_L1TP_060247_20180905_20180912_01_T1_L1TP' AND collec Note that `filter-lang` defaults to `cql-json` in this case. The parameter `filter-crs` defaults to `http://www.opengis.net/def/crs/OGC/1.3/CRS84` for a STAC API. -```javascript -POST /search +```json { "filter": { "and": [ @@ -490,8 +492,8 @@ OGC API Features filters only operate against a single collection already. #### Example 2: GET with cql-text -```javascript -GET /search?filter=collection = 'landsat8_l1tp' +``` +filter=collection = 'landsat8_l1tp' AND gsd <= 30 AND eo:cloud_cover <= 10 AND datetime >= "2021-04-08T04:39:23Z" @@ -501,8 +503,7 @@ GET /search?filter=collection = 'landsat8_l1tp' #### Example 2: POST with cql-json -```javascript -POST /search +```json { "filter-lang": "cql-json", "filter": { @@ -570,14 +571,13 @@ This queryables JSON Schema is used in these examples: #### Example 3: GET with cql-text -```javascript -GET /search?filter=prop1 = prop2 +``` +filter=prop1 = prop2 ``` #### Example 3: POST with cql-json -```javascript -POST /search +```json { "filter-lang": "cql-json", "filter": { @@ -683,8 +683,8 @@ a tiny sliver of data. #### Example 4: AND cql-text (GET) -```javascript -/search?filter=sentinel:data_coverage > 50 AND eo:cloud_cover < 10 +``` +filter=sentinel:data_coverage > 50 AND eo:cloud_cover < 10 ``` #### Example 4: AND cql-json (POST) @@ -710,8 +710,8 @@ This uses the same queryables as Example 4. #### Example 5: OR cql-text (GET) -```javascript -/search?filter=sentinel:data_coverage > 50 OR eo:cloud_cover < 10 +``` +filter=sentinel:data_coverage > 50 OR eo:cloud_cover < 10 ``` #### Example 5: OR cql-json (POST) @@ -737,8 +737,8 @@ have any overlap between them. #### Example 6: ANYINTERACTS cql-text (GET) -```javascript -/search?filter=datetime ANYINTERACTS 2020-11-11T00:00:00Z/2020-11-12T00:00:00Z +``` +filter=datetime ANYINTERACTS 2020-11-11T00:00:00Z/2020-11-12T00:00:00Z ``` #### Example 6: ANYINTERACTS cql-json (POST) @@ -764,8 +764,8 @@ format uses GeoJSON geometries. #### Example 7: INTERSECTS cql-text (GET) -```javascript -/search?filter=INTERSECTS(geometry,POLYGON((-77.0824 38.7886,-77.0189 38.7886,-77.0189 38.8351,-77.0824 38.8351,-77.0824 38.7886))) +``` +filter=INTERSECTS(geometry,POLYGON((-77.0824 38.7886,-77.0189 38.7886,-77.0189 38.8351,-77.0824 38.8351,-77.0824 38.7886))) ``` #### Example 7: INTERSECTS cql-json (POST) @@ -798,8 +798,8 @@ logical operator. #### Example 8: INTERSECTS cql-text (GET) -```javascript -/search?filter=INTERSECTS(geometry,POLYGON((-77.0824 38.7886,-77.0189 38.7886,-77.0189 38.8351,-77.0824 38.8351,-77.0824 38.7886))) OR INTERSECTS(geometry,POLYGON((-79.0935 38.7886,-79.0290 38.7886,-79.0290 38.8351,-79.0935 38.8351,-79.0935 38.7886))) +``` +filter=INTERSECTS(geometry,POLYGON((-77.0824 38.7886,-77.0189 38.7886,-77.0189 38.8351,-77.0824 38.8351,-77.0824 38.7886))) OR INTERSECTS(geometry,POLYGON((-79.0935 38.7886,-79.0290 38.7886,-79.0290 38.8351,-79.0935 38.8351,-79.0935 38.7886))) ``` #### Example 8: INTERSECTS cql-json (POST) @@ -846,8 +846,8 @@ either of those properties. #### Example 9: cql-text (GET) -```javascript -/search?filter=sentinel:data_coverage > 50 OR landsat:coverage_percent < 10 OR (sentinel:data_coverage IS NULL AND landsat:coverage_percent IS NULL) +``` +filter=sentinel:data_coverage > 50 OR landsat:coverage_percent < 10 OR (sentinel:data_coverage IS NULL AND landsat:coverage_percent IS NULL) ``` #### Example 9: cql-json (POST) From 63dac3d304b7f22dc0babd0cba1db84ca8be7a4e Mon Sep 17 00:00:00 2001 From: Phil Varner Date: Tue, 5 Oct 2021 12:27:24 -0400 Subject: [PATCH 14/14] merge --- fragments/filter/README.md | 18 +++++++++--------- implementation.md | 8 -------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/fragments/filter/README.md b/fragments/filter/README.md index 3e8b603c..5fb7d386 100644 --- a/fragments/filter/README.md +++ b/fragments/filter/README.md @@ -463,7 +463,7 @@ This example uses the queryables definition in (Interaction with Endpoints)(#int Note that `filter-lang` defaults to `cql-text` in this case. The parameter `filter-crs` defaults to `http://www.opengis.net/def/crs/OGC/1.3/CRS84` for a STAC API. -``` +```http filter=id='LC08_L1TP_060247_20180905_20180912_01_T1_L1TP' AND collection='landsat8_l1tp' ``` @@ -492,7 +492,7 @@ OGC API Features filters only operate against a single collection already. #### Example 2: GET with cql-text -``` +```http filter=collection = 'landsat8_l1tp' AND gsd <= 30 AND eo:cloud_cover <= 10 @@ -571,7 +571,7 @@ This queryables JSON Schema is used in these examples: #### Example 3: GET with cql-text -``` +```http filter=prop1 = prop2 ``` @@ -683,7 +683,7 @@ a tiny sliver of data. #### Example 4: AND cql-text (GET) -``` +```http filter=sentinel:data_coverage > 50 AND eo:cloud_cover < 10 ``` @@ -710,7 +710,7 @@ This uses the same queryables as Example 4. #### Example 5: OR cql-text (GET) -``` +```http filter=sentinel:data_coverage > 50 OR eo:cloud_cover < 10 ``` @@ -737,7 +737,7 @@ have any overlap between them. #### Example 6: ANYINTERACTS cql-text (GET) -``` +```http filter=datetime ANYINTERACTS 2020-11-11T00:00:00Z/2020-11-12T00:00:00Z ``` @@ -764,7 +764,7 @@ format uses GeoJSON geometries. #### Example 7: INTERSECTS cql-text (GET) -``` +```http filter=INTERSECTS(geometry,POLYGON((-77.0824 38.7886,-77.0189 38.7886,-77.0189 38.8351,-77.0824 38.8351,-77.0824 38.7886))) ``` @@ -798,7 +798,7 @@ logical operator. #### Example 8: INTERSECTS cql-text (GET) -``` +```http filter=INTERSECTS(geometry,POLYGON((-77.0824 38.7886,-77.0189 38.7886,-77.0189 38.8351,-77.0824 38.8351,-77.0824 38.7886))) OR INTERSECTS(geometry,POLYGON((-79.0935 38.7886,-79.0290 38.7886,-79.0290 38.8351,-79.0935 38.8351,-79.0935 38.7886))) ``` @@ -846,7 +846,7 @@ either of those properties. #### Example 9: cql-text (GET) -``` +```http filter=sentinel:data_coverage > 50 OR landsat:coverage_percent < 10 OR (sentinel:data_coverage IS NULL AND landsat:coverage_percent IS NULL) ``` diff --git a/implementation.md b/implementation.md index 3292c1e8..2b61cd75 100644 --- a/implementation.md +++ b/implementation.md @@ -70,19 +70,11 @@ RFC 3339 datetime or an interval) is: language standard libraries do not parse ISO8601 datetimes correctly, for example, the built-in Python datetime library does not handle `Z` as a timezone. -<<<<<<< HEAD Below are a few examples of valid RFC 3339 datetimes. Note the uses of fractional seconds, the use of `.` as the fractional seconds separator, Z (recommended) or z as a timezone, positive and negative arbitrary offset timezones, and T (recommended) or t as a separator between date and time. While the RFC 3339 spec does not define the required number of fractional seconds, STAC API only requires up to 9 digits be supported. -======= -Below are a few examples of valid RFC 3339 datetimes. Note the uses of fractional seconds, -the use of `.` as the fractional seconds separator, Z or z as a timezone, -positive and negative arbitrary offset timezones, and T or t as a separator between date and -time. While the RFC 3339 spec does not define the required number of fractional seconds, -STAC API only requires up to 9 digits be supported. ->>>>>>> dev - 1990-12-31T23:59:59Z (no fractional seconds, Z timezone) - 1990-12-31T23:59:23.123Z (fractional seconds, Z timezone)