Filtering and reprojecting data

OGC API - Features CRS extension

The OGC API Core specification states CRS84 is the only Coordinate Reference System an implementation must support. Therefore Geo-spatial data stored in a different CRS must be reprojected to CRS84.

This means that by default a collection of features will not be returned with the native CRS defined at layer configuration time. E.g. the native CRS of the bugsites layer is EPSG:26713, but by default the collection will be returned using EPSG:4326.

GeoServer implementation of Feature Service supports reprojection as described by Coordinate Reference Systems by Reference specification.

To obtain a response with a CRS other than CRS84 the crs parameter needs to be specified, for example:

http://localhost:8083/geoserver/ogc/features/v1/
collections/
sf:bugsites/
items?f=application%2Fgeo%2Bjson&limit=50&crs=EPSG:26713

To clearly and unambiguously assert the CRS being used in a response document independent of the requested output format, the response will contain a header named ``Content-Crs: `` asserting the Coordinate Reference System that has been used.

Warning

The GeoJSON specification always assumes data in CRS84. Usage of other coordinate reference system is left to a “prior arrangement between parties”. The OGC API - Features CRS extension is such arrangement, the client is explicitly asking for a different CRS. OGC is moving beyond this limitation with the new OGC Features and Geometry JSON specification.

BBOX filtering

The bbox parameter allows searching for features overlapping a user specified bounding box. By default the service will interpret the bbox coordinates as CRS84. If another CRS is needed, the CRS extension must be implemented by the server, and the parameter bbox-crs needs to be provided.

Using as an example the bugsites collection, a request with a bbox filter will look like the following:

http://localhost:8083/geoserver/ogc/features/v1/
collections/
sf:bugsites/
items?f=application%2Fgeo%2Bjson&bbox=597650.6042788428,4919751.718018367,601315.4744029717,4922314.263925473&bbox-crs=EPSG:26713

where the bbox-crs has as a value EPSG:26713, matching the collection native CRS.

Filtering and the Common Query Language

Part 3, Filter

GeoServer OGCAPI - Features provides filtering capability by implementing the Filtering extension as defined in OGC API - Features - Part 3 : Filtering specification.

The specifications define the following query parameters:

  • filter-lang, the language used to specify the filter
  • filter, the filter definition itself
  • filter-crs, the CRS used in eventual geometry literals found in the filter

Queryables

Queryables allow to determine the names and types of the properties that may be used to construct a filter.

A queryable might not overlap completely with the content schema of a resource. A publisher may want to support queryables that are not directly represented as properties in the original schema (happened in CSW as well), or may want to restrict filtering on certain properties.

Queryables resources can be requested for each collection of items at /collections/{collectionId}/queryables. Eg. for the bugsites collection, queryables can be retrieved at http://localhost:8083/geoserver/ogc/features/v1/collections/sf:bugsites/queryables, providing the following response:

../../_images/queryables.png

A queryable can also be requested as a JSON using the application/schema+json MIME type. http://localhost:8083/geoserver/ogc/features/v1/collections/sf:bugsites/queryables?f=application%2Fschema%2Bjson will produce the following output:

 {
  "title":"Spearfish bug locations",
  "type":"object",
  "properties":{
     "the_geom":{
        "$ref":"https://geojson.org/schema/Point.json"
     },
     "cat":{
        "type":"integer",
        "description":"integer"
     },
     "str1":{
        "type":"string",
        "description":"string"
     }
  },
  "$schema":"https://json-schema.org/draft/2019-09/schema",
  "$id":"http://localhost:8083/geoserver/ogc/features/v1/collections/sf%3Abugsites/queryables"
}

CQL2

The Common Query Language 2 specification defines concepts and grammars for a filtering language, with two possible syntaxes at the moment: a text based one, reminiscent of the SQL WHERE clause, and a JSON based on.

While at the beginning it was quite consistent with GeoServer own ECQL (Extended CQL), it eventually took its own path and shows differences in more advanced filters (spatial, temporal).

Filtering examples

Filter parameter

The filter parameter allows to specify a predicate to filter data. The filter-lang parameter specifies which filtering language is used in filter. A server might support multiple filtering languages.

Currently, geoServer supports the following languages:

  • cql2-text, text based specification similar, to some extents, to SQL (the default one).
  • cql2-json, a JSON based filtering language with the same semantics as cql2-text.
  • ecql-text, GeoServer own Extended CQL

If the filter language is different from cql2-text the additional filter-lang parameter needs to be used, e.g. filter-lang=cql2-json.

The following request is filtering the bugsites items with a cat value lower than 6

http://localhost:8083/geoserver/ogc/features/v1/collections/sf:bugsites/items?f=application%2Fgeo%2Bjson&filter=cat<6

and produces the following output:

  {
  "type":"FeatureCollection",
  "features":[
     {
        "type":"Feature",
        "id":"bugsites.1",
        "geometry":{
           "type":"Point",
           "coordinates":[
              -103.86761148,
              44.38484141
           ]
        },
        "geometry_name":"the_geom",
        "properties":{
           "cat":1,
           "str1":"Beetle site"
        }
     },
     {
        "type":"Feature",
        "id":"bugsites.2",
        "geometry":{
           "type":"Point",
           "coordinates":[
              -103.86509752,
              44.38630194
           ]
        },
        "geometry_name":"the_geom",
        "properties":{
           "cat":2,
           "str1":"Beetle site"
        }
     },
     {
        "type":"Feature",
        "id":"bugsites.3",
        "geometry":{
           "type":"Point",
           "coordinates":[
              -103.86395564,
              44.38107792
           ]
        },
        "geometry_name":"the_geom",
        "properties":{
           "cat":3,
           "str1":"Beetle site"
        }
     },
     {
        "type":"Feature",
        "id":"bugsites.4",
        "geometry":{
           "type":"Point",
           "coordinates":[
              -103.86361552,
              44.38762863
           ]
        },
        "geometry_name":"the_geom",
        "properties":{
           "cat":4,
           "str1":"Beetle site"
        }
     },
     {
        "type":"Feature",
        "id":"bugsites.5",
        "geometry":{
           "type":"Point",
           "coordinates":[
              -103.86279282,
              44.38732335
           ]
        },
        "geometry_name":"the_geom",
        "properties":{
           "cat":5,
           "str1":"Beetle site"
        }
     }
  ],
  "totalFeatures":9,
  "numberMatched":9,
  "numberReturned":9,
  "timeStamp":"2021-09-16T08:57:51.319Z",
  "crs":{
     "type":"name",
     "properties":{
        "name":"urn:ogc:def:crs:EPSG::4326"
     }
  }
}

The following request uses instead a spatial intersects filter, requesting all the features whose geometry intersects the polygon:

Polygon ((-103.85926203756271491 44.40889374215363006, -103.84972983657543466 44.4080809188136314, -103.84943426445180137 44.39987879238272228, -103.85992707484089692 44.400248257537271, -103.85926203756271491 44.40889374215363006))

The request split by lines is:

http://localhost:8083/geoserver/ogc/features/v1/
collections/sf:bugsites/items?f=application%2Fgeo%2Bjson
&filter=s_intersects(the_geom,Polygon ((-103.85926203756271491 44.40889374215363006, -103.84972983657543466 44.4080809188136314, -103.84943426445180137 44.39987879238272228, -103.85992707484089692 44.400248257537271, -103.85926203756271491 44.40889374215363006)))

and produces the following output:

 {
  "type":"FeatureCollection",
  "features":[
     {
        "type":"Feature",
        "id":"bugsites.15",
        "geometry":{
           "type":"Point",
           "coordinates":[
              -103.85723792,
              44.40632697
           ]
        },
        "geometry_name":"the_geom",
        "properties":{
           "cat":15,
           "str1":"Beetle site"
        }
     },
     {
        "type":"Feature",
        "id":"bugsites.23",
        "geometry":{
           "type":"Point",
           "coordinates":[
              -103.85229087,
              44.40434176
           ]
        },
        "geometry_name":"the_geom",
        "properties":{
           "cat":23,
           "str1":"Beetle site"
        }
     }
  ],
  "numberMatched":2,
  "numberReturned":2,
  "timeStamp":"2021-09-16T12:45:33.796Z"
}

Limit items

It is possible to limit the number of features returned by using the limit parameter. For example, the following request will return at most 3 items from the bugsites collection:

http://localhost:8083/geoserver/ogc/features/v1/collections/sf:bugsites/items?f=application%2Fgeo%2Bjson&limit=3
 {
  "type":"FeatureCollection",
  "features":[
     {
        "type":"Feature",
        "id":"bugsites.1",
        "geometry":{
           "type":"Point",
           "coordinates":[
              -103.86761148,
              44.38484141
           ]
        },
        "geometry_name":"the_geom",
        "properties":{
           "cat":1,
           "str1":"Beetle site"
        }
     },
     {
        "type":"Feature",
        "id":"bugsites.10",
        "geometry":{
           "type":"Point",
           "coordinates":[
              -103.85881675,
              44.38906627
           ]
        },
        "geometry_name":"the_geom",
        "properties":{
           "cat":10,
           "str1":"Beetle site"
        }
     },
     {
        "type":"Feature",
        "id":"bugsites.11",
        "geometry":{
           "type":"Point",
           "coordinates":[
              -103.85882875,
              44.37746168
           ]
        },
        "geometry_name":"the_geom",
        "properties":{
           "cat":11,
           "str1":"Beetle site"
        }
     }
  ],
  "totalFeatures":90,
  "numberMatched":90,
  "numberReturned":3,
  "timeStamp":"2021-09-16T09:26:55.938Z",
  "links":[
     {
        "title":"next page",
        "type":"application/json",
        "rel":"next",
        "href":"http://localhost:8083/geoserver/ogc/features/v1/collections/sf%3Abugsites/items?limit=3&f=application%2Fjson&startIndex=3"
     }
  ],
  "crs":{
     "type":"name",
     "properties":{
        "name":"urn:ogc:def:crs:EPSG::4326"
     }
  }
}