Skip to content

OGCAPI Features Part 3 Filtering: add support for 'Queryables' and 'Queryables as query parameter' - #7433

Merged
rouault merged 2 commits into
MapServer:mainfrom
rouault:ogcapi_part3_queryables
Feb 17, 2026
Merged

rouault merged 2 commits into
MapServer:mainfrom
rouault:ogcapi_part3_queryables

Conversation

@rouault

@rouault rouault commented Feb 13, 2026 •

Copy link
Copy Markdown
Contributor

Support 2 conformance classes of OGCAPI Features Part 3 Filtering (more to come)

Add a new layer metadata item "oga_queryables" to define the list of
items that can be queried. Defaults to none. Can be set to 'all', or a
comma separated list of items. Exactly like "gml_include_items"

LAYER
   METADATA
      "oga_queryable_items" "CTY_NAME,CTYONLY_,LASTMOD"
   END
END
$ mapserv -conf ../etc/mapserv.conf "PATH_INFO=/ogcapi.map/ogcapi/collections/mn_counties/queryables" "QUERY_STRING=f=json" -nh | jq .
{
  "$id": "http://localhost/cgi-bin/mapserv/OGCAPI_TEST/ogcapi/collections/mn_counties/queryables",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": false,
  "description": "This is the standard Minnesota State County Boundary dataset.",
  "properties": {
    "CTYONLY_": {
      "description": "Queryable item 'CTYONLY_'",
      "type": "integer"
    },
    "Name": {
      "description": "Queryable item 'Name'",
      "type": "string"
    },
    "LASTMOD": {
      "description": "Queryable item 'LASTMOD'",
      "format": "date-time",
      "type": "string"
    }
  },
  "title": "State of Minnesota County Boundaries",
  "type": "object"
}
$ mapserv -conf ../etc/mapserv.conf "PATH_INFO=/ogcapi.map/ogcapi/collections/mn_counties/items" "QUERY_STRING=f=json&Name=Rice"
Content-Type: application/geo+json
Content-Crs: <http://www.opengis.net/def/crs/OGC/1.3/CRS84>
Link: <http://localhost/cgi-bin/mapserv/OGCAPI_TEST/ogcapi/collections/mn_counties/items?f=json&limit=9&offset=0&Name=Rice>; rel="self"; title="Items for this collection as GeoJSON"; type="application/geo+json"
Link: <http://localhost/cgi-bin/mapserv/OGCAPI_TEST/ogcapi/collections/mn_counties/items?f=html&limit=9&offset=0&Name=Rice>; rel="alternate"; title="Items for this collection as HTML"; type="text/html"
OGC-NumberMatched: 1
OGC-NumberReturned: 1

{"features":[{"geometry":{"coordinates":[[[-93.5242,44.5436],[-93.5225,44.5436],[-93.504,44.5438],[-93.5018,44.5438],[-93.4835,44.5438],[-93.4817,44.5438],[-93.4734,44.5438],[-93.4632,44.5438],[-93.4609,44.5438],[-93.4429,44.5438],[-93.4408,44.5438],[-93.4326,44.5438],[-93.4226,44.5439],[-93.4206,44.5439],[-93.4024,44.5439],[-93.4003,44.5439],[-93.383,44.544],[-93.38,44.544],[-93.3627,44.5441],[-93.3596,44.5441],[-93.3556,44.5441],[-93.3424,44.5442],[-93.3395,44.5442],[-93.3221,44.544],[-93.3191,44.544],[-93.3128,44.544],[-93.3019,44.544],[-93.2988,44.544],[-93.2813,44.544],[-93.2814,44.5298],[-93.2815,44.5153],[-93.2815,44.501],[-93.2815,44.4865],[-93.2817,44.472],[-93.2618,44.4718],[-93.2415,44.4716],[-93.2213,44.4714],[-93.2008,44.4714],[-93.1808,44.4713],[-93.1605,44.4713],[-93.1408,44.4712],[-93.1206,44.4713],[-93.1002,44.4718],[-93.0799,44.4719],[-93.0597,44.4718],[-93.0393,44.4719],[-93.0394,44.4576],[-93.0396,44.4432],[-93.0397,44.4287],[-93.0399,44.4143],[-93.04,44.3999],[-93.0401,44.3855],[-93.0402,44.371],[-93.0403,44.3565],[-93.0403,44.3419],[-93.0405,44.3273],[-93.0405,44.3129],[-93.0405,44.2983],[-93.0406,44.2838],[-93.0407,44.2693],[-93.0409,44.2548],[-93.041,44.2402],[-93.0411,44.2257],[-93.0411,44.2113],[-93.0411,44.1968],[-93.0427,44.1968],[-93.0459,44.1968],[-93.0613,44.1967],[-93.0661,44.1967],[-93.0815,44.1967],[-93.0862,44.1967],[-93.1003,44.1967],[-93.1015,44.1967],[-93.1063,44.1967],[-93.1092,44.1967],[-93.1218,44.1967],[-93.1267,44.1967],[-93.1301,44.1967],[-93.1418,44.1967],[-93.1467,44.1967],[-93.1561,44.1966],[-93.1622,44.1966],[-93.1661,44.1966],[-93.1703,44.1966],[-93.1822,44.1966],[-93.1856,44.1966],[-93.1865,44.1966],[-93.2023,44.1966],[-93.2037,44.1966],[-93.2064,44.1966],[-93.2225,44.1966],[-93.2265,44.1966],[-93.2292,44.1966],[-93.2426,44.1966],[-93.2465,44.1966],[-93.255,44.1966],[-93.2629,44.1966],[-93.2664,44.1966],[-93.2767,44.1966],[-93.283,44.1966],[-93.2865,44.1965],[-93.2905,44.1965],[-93.3032,44.1965],[-93.3063,44.1965],[-93.3235,44.1965],[-93.3264,44.1965],[-93.3277,44.1965],[-93.3436,44.1965],[-93.3466,44.1965],[-93.3639,44.1965],[-93.3666,44.1965],[-93.3842,44.1965],[-93.3866,44.1965],[-93.4042,44.1965],[-93.4065,44.1965],[-93.4244,44.1964],[-93.4267,44.1964],[-93.4447,44.1964],[-93.4469,44.1964],[-93.4648,44.1963],[-93.467,44.1963],[-93.4852,44.1964],[-93.4872,44.1964],[-93.5053,44.1963],[-93.507,44.1963],[-93.5255,44.1962],[-93.5253,44.2107],[-93.5251,44.2251],[-93.5251,44.2388],[-93.5251,44.2533],[-93.5252,44.2685],[-93.5252,44.2829],[-93.5252,44.2975],[-93.5252,44.312],[-93.5249,44.3266],[-93.5249,44.3411],[-93.5245,44.3557],[-93.5245,44.3704],[-93.5246,44.3848],[-93.5245,44.3994],[-93.5245,44.4138],[-93.5245,44.4283],[-93.5245,44.4427],[-93.5245,44.4572],[-93.5244,44.4717],[-93.5245,44.4862],[-93.5244,44.5007],[-93.5243,44.5152],[-93.5244,44.5297],[-93.5242,44.5436]]],"type":"Polygon"},"id":"66","properties":{"Area":1335114621.00336,"CTYONLY_":66,"Code":"RICE","LASTMOD":"2010-10-17T00:00:00Z","Name":"Rice","Perimiter":154431.78788},"type":"Feature"}],"links":[{"href":"http://localhost/cgi-bin/mapserv/OGCAPI_TEST/ogcapi/collections/mn_counties/items?f=json&limit=9&offset=0&Name=Rice","rel":"self","title":"Items for this collection as GeoJSON","type":"application/geo+json"},{"href":"http://localhost/cgi-bin/mapserv/OGCAPI_TEST/ogcapi/collections/mn_counties/items?f=html&limit=9&offset=0&Name=Rice","rel":"alternate","title":"Items for this collection as HTML","type":"text/html"}],"numberMatched":1,"numberReturned":1,"type":"FeatureCollection"}

and make it default to true.

That parameter was removed per PR MapServer#7360 which added support for a
extra_params configuration item.

This PR adds the param names from the extra_params as allowed parameters
to validate the query parameters. This is a pre-requisite for the
to-come support of "Queryables as Query Parameters" of
OGC API Features - Part 3 : https://docs.ogc.org/is/19-079r2/19-079r2.html#queryables-query-parameters
@rouault rouault added this to the 8.8.0 Release milestone Feb 13, 2026
@rouault
rouault force-pushed the ogcapi_part3_queryables branch from a173434 to f17c704 Compare February 13, 2026 01:26
…as query parameter'

Support 2 conformance classes of OGCAPI Features Part 3 Filtering (more to come)

- http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/queryables-query-parameters

Add a new layer metadata item "oga_queryables" to define the list of
items that can be queried. Defaults to none. Can be set to 'all', or a
comma separated list of items. Exactly like "gml_include_items"

```
LAYER
   METADATA
      "oga_queryable_items" "CTY_NAME,CTYONLY_,LASTMOD"
   END
END
```

```
$ mapserv -conf ../etc/mapserv.conf "PATH_INFO=/ogcapi.map/ogcapi/collections/mn_counties/queryables" "QUERY_STRING=f=json" -nh | jq .
```

```json
{
  "$id": "http://localhost/cgi-bin/mapserv/OGCAPI_TEST/ogcapi/collections/mn_counties/queryables",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": false,
  "description": "This is the standard Minnesota State County Boundary dataset.",
  "properties": {
    "CTYONLY_": {
      "description": "Queryable item 'CTYONLY_'",
      "type": "integer"
    },
    "Name": {
      "description": "Queryable item 'Name'",
      "type": "string"
    },
    "LASTMOD": {
      "description": "Queryable item 'LASTMOD'",
      "format": "date-time",
      "type": "string"
    }
  },
  "title": "State of Minnesota County Boundaries",
  "type": "object"
}
```

- http://www.opengis.net/spec/ogcapi-features-3/1.0/conf/queryables-query-parameters

```
$ mapserv -conf ../etc/mapserv.conf "PATH_INFO=/ogcapi.map/ogcapi/collections/mn_counties/items" "QUERY_STRING=f=json&Name=Rice"
```

```
Content-Type: application/geo+json
Content-Crs: <http://www.opengis.net/def/crs/OGC/1.3/CRS84>
Link: <http://localhost/cgi-bin/mapserv/OGCAPI_TEST/ogcapi/collections/mn_counties/items?f=json&limit=9&offset=0&Name=Rice>; rel="self"; title="Items for this collection as GeoJSON"; type="application/geo+json"
Link: <http://localhost/cgi-bin/mapserv/OGCAPI_TEST/ogcapi/collections/mn_counties/items?f=html&limit=9&offset=0&Name=Rice>; rel="alternate"; title="Items for this collection as HTML"; type="text/html"
OGC-NumberMatched: 1
OGC-NumberReturned: 1

{"features":[{"geometry":{"coordinates":[[[-93.5242,44.5436],[-93.5225,44.5436],[-93.504,44.5438],[-93.5018,44.5438],[-93.4835,44.5438],[-93.4817,44.5438],[-93.4734,44.5438],[-93.4632,44.5438],[-93.4609,44.5438],[-93.4429,44.5438],[-93.4408,44.5438],[-93.4326,44.5438],[-93.4226,44.5439],[-93.4206,44.5439],[-93.4024,44.5439],[-93.4003,44.5439],[-93.383,44.544],[-93.38,44.544],[-93.3627,44.5441],[-93.3596,44.5441],[-93.3556,44.5441],[-93.3424,44.5442],[-93.3395,44.5442],[-93.3221,44.544],[-93.3191,44.544],[-93.3128,44.544],[-93.3019,44.544],[-93.2988,44.544],[-93.2813,44.544],[-93.2814,44.5298],[-93.2815,44.5153],[-93.2815,44.501],[-93.2815,44.4865],[-93.2817,44.472],[-93.2618,44.4718],[-93.2415,44.4716],[-93.2213,44.4714],[-93.2008,44.4714],[-93.1808,44.4713],[-93.1605,44.4713],[-93.1408,44.4712],[-93.1206,44.4713],[-93.1002,44.4718],[-93.0799,44.4719],[-93.0597,44.4718],[-93.0393,44.4719],[-93.0394,44.4576],[-93.0396,44.4432],[-93.0397,44.4287],[-93.0399,44.4143],[-93.04,44.3999],[-93.0401,44.3855],[-93.0402,44.371],[-93.0403,44.3565],[-93.0403,44.3419],[-93.0405,44.3273],[-93.0405,44.3129],[-93.0405,44.2983],[-93.0406,44.2838],[-93.0407,44.2693],[-93.0409,44.2548],[-93.041,44.2402],[-93.0411,44.2257],[-93.0411,44.2113],[-93.0411,44.1968],[-93.0427,44.1968],[-93.0459,44.1968],[-93.0613,44.1967],[-93.0661,44.1967],[-93.0815,44.1967],[-93.0862,44.1967],[-93.1003,44.1967],[-93.1015,44.1967],[-93.1063,44.1967],[-93.1092,44.1967],[-93.1218,44.1967],[-93.1267,44.1967],[-93.1301,44.1967],[-93.1418,44.1967],[-93.1467,44.1967],[-93.1561,44.1966],[-93.1622,44.1966],[-93.1661,44.1966],[-93.1703,44.1966],[-93.1822,44.1966],[-93.1856,44.1966],[-93.1865,44.1966],[-93.2023,44.1966],[-93.2037,44.1966],[-93.2064,44.1966],[-93.2225,44.1966],[-93.2265,44.1966],[-93.2292,44.1966],[-93.2426,44.1966],[-93.2465,44.1966],[-93.255,44.1966],[-93.2629,44.1966],[-93.2664,44.1966],[-93.2767,44.1966],[-93.283,44.1966],[-93.2865,44.1965],[-93.2905,44.1965],[-93.3032,44.1965],[-93.3063,44.1965],[-93.3235,44.1965],[-93.3264,44.1965],[-93.3277,44.1965],[-93.3436,44.1965],[-93.3466,44.1965],[-93.3639,44.1965],[-93.3666,44.1965],[-93.3842,44.1965],[-93.3866,44.1965],[-93.4042,44.1965],[-93.4065,44.1965],[-93.4244,44.1964],[-93.4267,44.1964],[-93.4447,44.1964],[-93.4469,44.1964],[-93.4648,44.1963],[-93.467,44.1963],[-93.4852,44.1964],[-93.4872,44.1964],[-93.5053,44.1963],[-93.507,44.1963],[-93.5255,44.1962],[-93.5253,44.2107],[-93.5251,44.2251],[-93.5251,44.2388],[-93.5251,44.2533],[-93.5252,44.2685],[-93.5252,44.2829],[-93.5252,44.2975],[-93.5252,44.312],[-93.5249,44.3266],[-93.5249,44.3411],[-93.5245,44.3557],[-93.5245,44.3704],[-93.5246,44.3848],[-93.5245,44.3994],[-93.5245,44.4138],[-93.5245,44.4283],[-93.5245,44.4427],[-93.5245,44.4572],[-93.5244,44.4717],[-93.5245,44.4862],[-93.5244,44.5007],[-93.5243,44.5152],[-93.5244,44.5297],[-93.5242,44.5436]]],"type":"Polygon"},"id":"66","properties":{"Area":1335114621.00336,"CTYONLY_":66,"Code":"RICE","LASTMOD":"2010-10-17T00:00:00Z","Name":"Rice","Perimiter":154431.78788},"type":"Feature"}],"links":[{"href":"http://localhost/cgi-bin/mapserv/OGCAPI_TEST/ogcapi/collections/mn_counties/items?f=json&limit=9&offset=0&Name=Rice","rel":"self","title":"Items for this collection as GeoJSON","type":"application/geo+json"},{"href":"http://localhost/cgi-bin/mapserv/OGCAPI_TEST/ogcapi/collections/mn_counties/items?f=html&limit=9&offset=0&Name=Rice","rel":"alternate","title":"Items for this collection as HTML","type":"text/html"}],"numberMatched":1,"numberReturned":1,"type":"FeatureCollection"}
```
@rouault
rouault force-pushed the ogcapi_part3_queryables branch from f17c704 to d61a265 Compare February 13, 2026 01:27
@geographika

Copy link
Copy Markdown
Member

Very nice! A great feature to base the 8.8 release around.

Comment thread src/maputil.c
*/
char *msBuildOnlineResource(mapObj *map, cgiRequestObj *req) {
char *msBuildOnlineResource(const mapObj *map, const cgiRequestObj *req) {
(void)map;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a question here as I am working on updating this function for RFC141. map is passed to this function, but then (void)map; is added (I think to avoid linter errors as it is unused). Do we keep map here to avoid breaking the API? Or was there a reason in the past to use map which is no longer the case?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we keep map here to avoid breaking the API? Or was there a reason in the past to use map which is no longer the case?

I didn't notice "map" wasn't used in that function. I'll keep it that way for now. A further cleanup could remove it if confirmed we don't need it.

@rouault
rouault merged commit 77820ff into MapServer:main Feb 17, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants