From a25c6cc905ef764356eb84df1b47625e24d5eaa2 Mon Sep 17 00:00:00 2001 From: John Schaap Date: Thu, 27 Aug 2026 14:51:45 +0200 Subject: [PATCH 1/6] extra pagina toegevoegd voor CQL filtering --- .../CQL-filtering met de BAG OGC API.md | 471 ++++++++++++++++++ 1 file changed, 471 insertions(+) create mode 100644 docs/features/CQL-filtering met de BAG OGC API.md diff --git a/docs/features/CQL-filtering met de BAG OGC API.md b/docs/features/CQL-filtering met de BAG OGC API.md new file mode 100644 index 0000000..e9be944 --- /dev/null +++ b/docs/features/CQL-filtering met de BAG OGC API.md @@ -0,0 +1,471 @@ +# CQL-filtering met de BAG OGC API + +## Leerdoelen + +Na het doorlopen van deze module kun je: + +- uitleggen wat CQL (Common Query Language) is; +- attributen filteren binnen een OGC API Features-collectie; +- eenvoudige CQL-expressies schrijven; +- meerdere filtervoorwaarden combineren met `AND`, `OR` en `NOT`; +- tekstfilters toepassen met `LIKE` en `IN`; +- CQL-filtering combineren met een ruimtelijke filter (`bbox`); +- BAG-adressen gericht opvragen met behulp van CQL. + +--- + +## Introductie + +Een OGC API Features-service kan grote hoeveelheden gegevens bevatten. Vaak ben je slechts geïnteresseerd in een klein deel van de dataset. + +Met **CQL (Common Query Language)** stuur je filtervoorwaarden mee naar de server. Hierdoor ontvang je alleen de objecten die voldoen aan de opgegeven criteria. Dit voorkomt onnodig dataverkeer en maakt applicaties efficiënter. + +In deze module gebruiken we de BAG OGC API collectie **Adres**: + +```text +https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items +``` + +--- + +## Wat is CQL? + +CQL is een gestandaardiseerde querytaal van het Open Geospatial Consortium (OGC) voor het filteren van geografische gegevens. + +Een filter wordt opgegeven via de queryparameter: + +```text +filter= +``` + +Een eenvoudige query ziet er als volgt uit: + +```http +https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items?filter=postcode='2513 AA' +``` + +Deze aanvraag retourneert helaas geen adressen, probeer het nogmaals zonder spatie in de postcode: + +```http +https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items?filter=postcode='2513 AA' +``` + +Deze retoneert uitsluitend adressen met postcode 2513 AA + +**:arrow_right: Vraag waarom werkt de eerst query niet en zonder spaties wel? ** +??? success "Bekijk het antwoord" + +In deze dataset is de postcode opgeslagen zonder spatie. Het SQL filter werkt direct op de waardes in de dataset. Een waarde voor postcode met spaties komt niet voor. + + + +--- + +## Beschikbare attributen om mee te filteren "Queryables" + +Voordat je een CQL-filter kunt schrijven, moet je weten op welke attributen gefilterd mag worden. Deze attributen worden binnen OGC API Features aangeduid als **queryables**. + +Queryables beschrijven de attributen van een object die gebruikt kunnen worden in een filterexpressie. Voor de BAG-adrescollectie zijn dat bijvoorbeeld attributen zoals `postcode`, `huisnummer`, `woonplaats_naam` en `openbare_ruimte_naam`. Deze velden zijn zichtbaar in de collectie en kunnen worden gebruikt in CQL-expressies. + +Voorbeelden van queryables binnen de BAG-adrescollectie zijn: + +```text +postcode +huisnummer +huisletter +woonplaats_naam +openbare_ruimte_naam +provincie_naam +status +adresseerbaar_object_type +``` + +Een queryable kan vervolgens direct in een filter worden gebruikt: + +```http +...?filter=postcode='2513AA' +``` + +of: + +```http +...?filter=woonplaats_naam='Den Haag' +``` + +Het concept *queryables* is belangrijk omdat niet ieder attribuut automatisch filterbaar is. Door de queryables van een collectie te raadplegen weet je welke eigenschappen door de API worden ondersteund voor filtering. Bij een OGC API Features-service kunnen queryables opgevraagd worden via het endpoint: + +```text +/collections/{collectionId}/queryables +``` + +Voor de BAG-adrescollectie is dat: + +```text +https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/queryables +``` + +Een goede werkwijze is om eerst de queryables te bekijken en daarna pas CQL-filters op te stellen. Zo voorkom je dat filters verwijzen naar velden die niet door de API ondersteund worden. Bij PDOK worden deze velden ook getoond onder +--- + + + +### Beschikbare mogelijkheden in een OGC API "Conformance Classes" + +Hoe weet je welke filtermogelijkheden een OGC API daadwerkelijk ondersteunt? + +Daarvoor kun je de **Conformance Classes** raadplegen. Een conformance class beschrijft een onderdeel van een OGC-standaard dat door een implementatie wordt ondersteund. De BAG OGC API publiceert deze informatie via het conformance-endpoint. + +Bekijk hiervoor: + +```text +https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/conformance +``` + +Wanneer je de conformance-pagina bekijkt zie je onder andere dat deze service ondersteuning biedt voor: + +- `ogcapi-features-3/conf/filter` +- `ogcapi-features-3/conf/features-filter` +- `ogcapi-features-3/conf/queryables` +- `ogcapi-features-3/conf/queryables-query-parameters` +- `cql2-text` +- `basic-cql2` +- `advanced-comparison-operators` +- `basic-spatial-functions` +- `spatial-functions` +- `temporal-functions` + +Dat betekent onder meer dat: + +| Conformance class | Betekenis | +|------------------|-----------| +| `filter` | De API ondersteunt filteren van features. | +| `features-filter` | Filters kunnen worden toegepast op een featurecollectie. | +| `queryables` | De API publiceert welke attributen filterbaar zijn. | +| `cql2-text` | CQL2-expressies kunnen als tekst worden aangeleverd. | +| `basic-cql2` | Basisoperatoren zoals `=`, `AND` en `OR` worden ondersteund. | +| `advanced-comparison-operators` | Extra vergelijkingsoperatoren zijn beschikbaar. | +| `spatial-functions` | Ruimtelijke functies kunnen in filters worden gebruikt. | +| `temporal-functions` | Tijdgerelateerde filters worden ondersteund. | + +Voordat je geavanceerde filters gaat gebruiken is het daarom verstandig om eerst het **conformance-endpoint** te bekijken. Daar kun je controleren welke onderdelen van CQL en OGC API Features door de betreffende service worden ondersteund. + +## Exacte vergelijkingen + +### Gelijk aan + +Zoek alle adressen in Appingedam: + +```http +...?filter=woonplaats_naam='Appingedam' +``` + +Zoek alle adressen met postcode 9901AA: + +```http +...?filter=postcode='9901AA' +``` + +### Ongelijk aan + +```http +...?filter=woonplaats_naam<>'Appingedam' +``` + +--- + +## Numerieke vergelijkingen + +Voor numerieke velden kunnen standaard vergelijkingsoperatoren worden gebruikt. + +### Groter dan + +```http +...?filter=huisnummer > 100 +``` + +### Kleiner dan + +```http +...?filter=huisnummer < 50 +``` + +### Beschikbare operatoren + +| Operator | Betekenis | +|-----------|-----------| +| = | gelijk aan | +| <> | ongelijk aan | +| < | kleiner dan | +| <= | kleiner dan of gelijk aan | +| > | groter dan | +| >= | groter dan of gelijk aan | + +--- + +## Meerdere voorwaarden combineren + +### AND + +Alle voorwaarden moeten waar zijn. + +```http +...?filter=woonplaats_naam='Appingedam' AND huisnummer > 10 +``` + +### OR + +Minimaal één voorwaarde moet waar zijn. + +```http +...?filter=woonplaats_naam='Appingedam' +OR woonplaats_naam='Sittard' +``` + +### NOT + +Keert een voorwaarde om. + +```http +...?filter=NOT woonplaats_naam='Appingedam' +``` + +--- + +## Tekstfiltering + +### LIKE + +Met `LIKE` kan gezocht worden op patronen. + +Zoek alle straatnamen die beginnen met "Snel": + +```http +...?filter=openbare_ruimte_naam LIKE 'Snel%' +``` + +Veelgebruikte wildcards: + +| Wildcard | Betekenis | +|-----------|-----------| +| % | nul of meer tekens | +| _ | exact één teken | + +Voorbeelden: + +```http +...?filter=openbare_ruimte_naam LIKE '%weg' +``` + +```http +...?filter=openbare_ruimte_naam LIKE 'Hoofd_%' +``` + +--- + +## Werken met IN + +Wanneer meerdere waarden toegestaan zijn, kan `IN` de query leesbaarder maken. + +```http +...?filter=woonplaats_naam IN ('Appingedam','Sittard') +``` + +Dit is functioneel gelijk aan: + +```http +...?filter=woonplaats_naam='Appingedam' +OR woonplaats_naam='Sittard' +``` + +--- + +## CQL combineren met een BBOX + +CQL kan gecombineerd worden met een ruimtelijke filter. + +Zoek adressen binnen een bepaald gebied én in Appingedam: + +```http +https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items? +bbox=6.82,53.31,6.85,53.33& +filter=woonplaats_naam='Appingedam' +``` + +Hiermee worden eerst objecten binnen de opgegeven bounding box geselecteerd. Vervolgens wordt de CQL-filter toegepast. + +--- + +## Praktijkvoorbeelden + +### Zoek een postcode + +```http +...?filter=postcode='9901AA' +``` + +### Zoek een postcode en huisnummer + +```http +...?filter=postcode='9901AA' AND huisnummer=13 +``` + +### Zoek alle adressen in Groningen + +```http +...?filter=provincie_naam='Groningen' +``` + +### Zoek alleen verblijfsobjecten + +```http +...?filter=adresseerbaar_object_type='Verblijfsobject' +``` + +### Zoek straten die beginnen met "Snel" + +```http +...?filter=openbare_ruimte_naam LIKE 'Snel%' +``` + +--- + +## URL-encoding + +CQL-expressies worden onderdeel van de URL. Speciale tekens en spaties moeten daarom worden geëncodeerd. + +Voorbeeld: + +```text +woonplaats_naam = 'Appingedam' +``` + +wordt: + +```text +woonplaats_naam%20%3D%20'Appingedam' +``` + +De meeste HTTP-clients en GIS-tools verzorgen dit automatisch. + +--- + +## Oefeningen +### Oefening 1 + +Maak een query die alle adressen in Appingedam retourneert. + +??? success "Antwoord" + + ```http + https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items? + filter=woonplaats_naam='Appingedam' + ``` + +--- + +### Oefening 2 + +Maak een query die alle adressen met postcode `9901AA` retourneert. + +??? success "Antwoord" + + ```http + https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items? + filter=postcode='9901AA' + ``` + +--- + +### Oefening 3 + +Maak een query die alle adressen met een huisnummer groter dan 50 retourneert. + +??? success "Antwoord" + + ```http + https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items? + filter=huisnummer > 50 + ``` + + Hierbij wordt het queryable `huisnummer` gebruikt in combinatie met de operator `>`. + +--- + +### Oefening 4 + +Maak een query die alle adressen retourneert waarvan de straatnaam begint met `Snel`. + +??? success "Antwoord" + + ```http + https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items? + filter=openbare_ruimte_naam LIKE 'Snel%' + ``` + + De wildcard `%` betekent: nul of meer willekeurige tekens. + +--- + +### Oefening 5 + +Combineer een `bbox` met een CQL-filter op woonplaats. + +??? success "Antwoord" + + ```http + https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items? + bbox=6.82,53.31,6.85,53.33& + filter=woonplaats_naam='Appingedam' + ``` + + Eerst worden de adressen binnen de bounding box geselecteerd. + Vervolgens worden alleen de adressen in woonplaats `Appingedam` teruggegeven. + +--- + +### Bonusopgave + +Zoek alle adressen van het Binnenhof in Den Haag met postcode `2513AA`. + +??? success "Antwoord" + + ```http + https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items? + filter=postcode='2513AA' + ``` + + Probeer deze query uit te breiden met een extra filter op + `openbare_ruimte_naam` of `huisnummer`. + +**Toelichting** + +In deze query worden twee filters gecombineerd: + +1. De `bbox` beperkt de resultaten tot een geografisch gebied. +2. De CQL-expressie selecteert alleen adressen waarvan de woonplaats `Appingedam` is. + +Daardoor worden uitsluitend adressen binnen het opgegeven gebied én in Appingedam geretourneerd. + +--- + +## Wat wordt ondersteund in welke API + +Met CQL kunnen gegevens direct op de server worden gefilterd. Hierdoor worden alleen de relevante objecten teruggestuurd, wat leidt tot efficiëntere zoekopdrachten, minder netwerkverkeer en kleinere responses. + +Veelgebruikte CQL-operatoren zijn: + +```text += +<> +< +<= +> +>= +AND +OR +NOT +LIKE +IN +``` + +Daarnaast ondersteunt deze BAG OGC API ook ruimtelijke filtering. Door CQL te combineren met een `bbox` of andere ruimtelijke functies kunnen zeer gerichte zoekopdrachten worden uitgevoerd. From 1297c5e86b578cb3f433b09a430bb0963cec441f Mon Sep 17 00:00:00 2001 From: John Schaap Date: Thu, 27 Aug 2026 15:10:39 +0200 Subject: [PATCH 2/6] duplicate tekst en typo's --- .../CQL-filtering met de BAG OGC API.md | 49 +++++-------------- 1 file changed, 12 insertions(+), 37 deletions(-) diff --git a/docs/features/CQL-filtering met de BAG OGC API.md b/docs/features/CQL-filtering met de BAG OGC API.md index e9be944..fd257f2 100644 --- a/docs/features/CQL-filtering met de BAG OGC API.md +++ b/docs/features/CQL-filtering met de BAG OGC API.md @@ -44,7 +44,7 @@ Een eenvoudige query ziet er als volgt uit: https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items?filter=postcode='2513 AA' ``` -Deze aanvraag retourneert helaas geen adressen, probeer het nogmaals zonder spatie in de postcode: +Deze aanvraag retourneert helaas geen adressen, probeer het nogmaals zonder spatie in de postcode: ```http https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items?filter=postcode='2513 AA' @@ -52,20 +52,18 @@ https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items?filter=p Deze retoneert uitsluitend adressen met postcode 2513 AA -**:arrow_right: Vraag waarom werkt de eerst query niet en zonder spaties wel? ** +**:arrow_right: Vraag waarom werkt de eerst query niet en zonder spaties wel?** ??? success "Bekijk het antwoord" In deze dataset is de postcode opgeslagen zonder spatie. Het SQL filter werkt direct op de waardes in de dataset. Een waarde voor postcode met spaties komt niet voor. - - --- ## Beschikbare attributen om mee te filteren "Queryables" Voordat je een CQL-filter kunt schrijven, moet je weten op welke attributen gefilterd mag worden. Deze attributen worden binnen OGC API Features aangeduid als **queryables**. -Queryables beschrijven de attributen van een object die gebruikt kunnen worden in een filterexpressie. Voor de BAG-adrescollectie zijn dat bijvoorbeeld attributen zoals `postcode`, `huisnummer`, `woonplaats_naam` en `openbare_ruimte_naam`. Deze velden zijn zichtbaar in de collectie en kunnen worden gebruikt in CQL-expressies. +Queryables beschrijven de attributen van een object die gebruikt kunnen worden in een filterexpressie. Voor de BAG-adrescollectie zijn dat bijvoorbeeld attributen zoals `postcode`, `huisnummer`, `woonplaats_naam` en `openbare_ruimte_naam`. Deze velden zijn zichtbaar in de collectie en kunnen worden gebruikt in CQL-expressies. Voorbeelden van queryables binnen de BAG-adrescollectie zijn: @@ -104,16 +102,14 @@ Voor de BAG-adrescollectie is dat: https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/queryables ``` -Een goede werkwijze is om eerst de queryables te bekijken en daarna pas CQL-filters op te stellen. Zo voorkom je dat filters verwijzen naar velden die niet door de API ondersteund worden. Bij PDOK worden deze velden ook getoond onder ---- - +Een goede werkwijze is om eerst de queryables te bekijken en daarna pas CQL-filters op te stellen. Zo voorkom je dat filters verwijzen naar velden die niet door de API ondersteund worden. Bij PDOK worden deze velden ook getoond onder ### Beschikbare mogelijkheden in een OGC API "Conformance Classes" Hoe weet je welke filtermogelijkheden een OGC API daadwerkelijk ondersteunt? -Daarvoor kun je de **Conformance Classes** raadplegen. Een conformance class beschrijft een onderdeel van een OGC-standaard dat door een implementatie wordt ondersteund. De BAG OGC API publiceert deze informatie via het conformance-endpoint. +Daarvoor kun je de **Conformance Classes** raadplegen. Een conformance class beschrijft een onderdeel van een OGC-standaard dat door een implementatie wordt ondersteund. De BAG OGC API publiceert deze informatie via het conformance-endpoint. Bekijk hiervoor: @@ -121,7 +117,7 @@ Bekijk hiervoor: https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/conformance ``` -Wanneer je de conformance-pagina bekijkt zie je onder andere dat deze service ondersteuning biedt voor: +Wanneer je de conformance-pagina bekijkt zie je onder andere dat deze service ondersteuning biedt voor: - `ogcapi-features-3/conf/filter` - `ogcapi-features-3/conf/features-filter` @@ -132,12 +128,12 @@ Wanneer je de conformance-pagina bekijkt zie je onder andere dat deze service on - `advanced-comparison-operators` - `basic-spatial-functions` - `spatial-functions` -- `temporal-functions` +- `temporal-functions` Dat betekent onder meer dat: | Conformance class | Betekenis | -|------------------|-----------| +| ------------------ | ----------- | | `filter` | De API ondersteunt filteren van features. | | `features-filter` | Filters kunnen worden toegepast op een featurecollectie. | | `queryables` | De API publiceert welke attributen filterbaar zijn. | @@ -147,7 +143,7 @@ Dat betekent onder meer dat: | `spatial-functions` | Ruimtelijke functies kunnen in filters worden gebruikt. | | `temporal-functions` | Tijdgerelateerde filters worden ondersteund. | -Voordat je geavanceerde filters gaat gebruiken is het daarom verstandig om eerst het **conformance-endpoint** te bekijken. Daar kun je controleren welke onderdelen van CQL en OGC API Features door de betreffende service worden ondersteund. +Voordat je geavanceerde filters gaat gebruiken is het daarom verstandig om eerst het **conformance-endpoint** te bekijken. Daar kun je controleren welke onderdelen van CQL en OGC API Features door de betreffende service worden ondersteund. ## Exacte vergelijkingen @@ -192,7 +188,7 @@ Voor numerieke velden kunnen standaard vergelijkingsoperatoren worden gebruikt. ### Beschikbare operatoren | Operator | Betekenis | -|-----------|-----------| +| ----------- | ----------- | | = | gelijk aan | | <> | ongelijk aan | | < | kleiner dan | @@ -246,7 +242,7 @@ Zoek alle straatnamen die beginnen met "Snel": Veelgebruikte wildcards: | Wildcard | Betekenis | -|-----------|-----------| +| ----------- | ----------- | | % | nul of meer tekens | | _ | exact één teken | @@ -350,6 +346,7 @@ De meeste HTTP-clients en GIS-tools verzorgen dit automatisch. --- ## Oefeningen + ### Oefening 1 Maak een query die alle adressen in Appingedam retourneert. @@ -447,25 +444,3 @@ In deze query worden twee filters gecombineerd: Daardoor worden uitsluitend adressen binnen het opgegeven gebied én in Appingedam geretourneerd. --- - -## Wat wordt ondersteund in welke API - -Met CQL kunnen gegevens direct op de server worden gefilterd. Hierdoor worden alleen de relevante objecten teruggestuurd, wat leidt tot efficiëntere zoekopdrachten, minder netwerkverkeer en kleinere responses. - -Veelgebruikte CQL-operatoren zijn: - -```text -= -<> -< -<= -> ->= -AND -OR -NOT -LIKE -IN -``` - -Daarnaast ondersteunt deze BAG OGC API ook ruimtelijke filtering. Door CQL te combineren met een `bbox` of andere ruimtelijke functies kunnen zeer gerichte zoekopdrachten worden uitgevoerd. From eda9a9113690eef0390eb536708f6d23f7f2688f Mon Sep 17 00:00:00 2001 From: John Schaap Date: Thu, 27 Aug 2026 15:27:49 +0200 Subject: [PATCH 3/6] ruimtelijk filteren toegevoegd via CQL --- .../Ruimtelijke filtering met CQL2.md | 390 ++++++++++++++++++ 1 file changed, 390 insertions(+) create mode 100644 docs/features/Ruimtelijke filtering met CQL2.md diff --git a/docs/features/Ruimtelijke filtering met CQL2.md b/docs/features/Ruimtelijke filtering met CQL2.md new file mode 100644 index 0000000..20d8c35 --- /dev/null +++ b/docs/features/Ruimtelijke filtering met CQL2.md @@ -0,0 +1,390 @@ +# Ruimtelijke filtering met CQL2 op de BAG Woonplaats-collectie + +## Leerdoelen + +Na het doorlopen van deze module kun je: + +- uitleggen wat ruimtelijke filtering is; +- het verschil benoemen tussen een `bbox` en een ruimtelijke CQL-filter; +- ruimtelijke relaties beschrijven met CQL2 spatial operators; +- bepalen welke spatial operators door een OGC API worden ondersteund; +- ruimtelijke filters combineren met attribuutfilters; +- spatial operators toepassen op de BAG Woonplaats-collectie. + +--- + +## Van BBOX naar ruimtelijke relaties + +In eerdere voorbeelden hebben we een `bbox` gebruikt om objecten binnen een rechthoekig gebied op te vragen. + +Voor de BAG Woonplaats-collectie: + +```http +https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/woonplaats/items? +bbox=4.28,52.05,4.33,52.09 +``` + +Met een bounding box selecteer je alle woonplaatsen die binnen het opgegeven gebied vallen. + +Soms wil je echter een specifiekere ruimtelijke relatie beschrijven: + +- Welke woonplaatsen liggen volledig binnen een gebied? +- Welke woonplaatsen raken een gebied? +- Welke woonplaatsen overlappen een gebied? +- Welke woonplaatsen liggen volledig buiten een gebied? + +Voor deze situaties ondersteunt de BAG OGC API ruimtelijke functies via CQL2. + +--- + +## Controleren of spatial operators worden ondersteund + +Elke OGC API publiceert via het endpoint `/conformance` welke delen van de standaard worden ondersteund. + +Voor de BAG API: + +```text +https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/conformance +``` + +Op de conformance-pagina zijn onder meer de volgende conformance classes aanwezig: + +```text +basic-spatial-functions +basic-spatial-functions-plus +spatial-functions +``` + +Deze conformance classes geven aan dat ruimtelijke CQL2-functies ondersteund worden. + +--- + +## Voorbeeldgeometrie + +In de voorbeelden gebruiken we een zoekgebied dat als polygoon wordt beschreven. + +```text +(5.04,52.11) +-------------------+ (5.05,52.11) + | | + | ZOEKGEBIED | + | | +(5.04,52.10) +-------------------+ (5.05,52.10) +``` + +Dezelfde geometrie in Well-Known Text (WKT): + +```wkt +POLYGON(( + 5.04 52.10, + 5.05 52.10, + 5.05 52.11, + 5.04 52.11, + 5.04 52.10 +)) +``` + +Dit gebied gebruiken we om woonplaatsgeometrieën mee te vergelijken. + +--- + +## S_INTERSECTS + +Zoek woonplaatsen die geheel of gedeeltelijk binnen het zoekgebied vallen. + +```cql +S_INTERSECTS( + geometry, + POLYGON(( + 5.04 52.10, + 5.05 52.10, + 5.05 52.11, + 5.04 52.11, + 5.04 52.10 + )) +) +``` + +Visualisatie: + +```text ++-------------------+ +| ####### | +| ########### | +| ####### | ++-------------------+ +``` + +Een deel van de woonplaats mag buiten het zoekgebied liggen. + +--- + +## S_WITHIN + +Zoek woonplaatsen die volledig binnen het zoekgebied liggen. + +```cql +S_WITHIN( + geometry, + POLYGON(( + 5.04 52.10, + 5.05 52.10, + 5.05 52.11, + 5.04 52.11, + 5.04 52.10 + )) +) +``` + +Visualisatie: + +```text ++-------------------+ +| | +| ##### | +| ##### | +| | ++-------------------+ +``` + +De volledige woonplaatsgeometrie moet binnen de polygoon liggen. + +--- + +## S_CONTAINS + +Zoek woonplaatsen die de opgegeven polygoon volledig bevatten. + +```cql +S_CONTAINS( + geometry, + POLYGON(( + 5.04 52.10, + 5.05 52.10, + 5.05 52.11, + 5.04 52.11, + 5.04 52.10 + )) +) +``` + +Visualisatie: + +```text +####################### +####################### +## +-------------+ ## +## | ZOEKGEBIED | ## +## +-------------+ ## +####################### +####################### +``` + +De woonplaats omvat het volledige zoekgebied. + +--- + +## S_TOUCHES + +Zoek woonplaatsen die de grens van het zoekgebied raken. + +```cql +S_TOUCHES( + geometry, + POLYGON(( + 5.04 52.10, + 5.05 52.10, + 5.05 52.11, + 5.04 52.11, + 5.04 52.10 + )) +) +``` + +Visualisatie: + +```text + ##### + ##### ++-------------------+ +| | +| | ++-------------------+ +``` + +De geometrieën delen alleen een grens of hoekpunt. + +--- + +## S_DISJOINT + +Zoek woonplaatsen die volledig buiten het zoekgebied liggen. + +```cql +S_DISJOINT( + geometry, + POLYGON(( + 5.04 52.10, + 5.05 52.10, + 5.05 52.11, + 5.04 52.11, + 5.04 52.10 + )) +) +``` + +Visualisatie: + +```text +##### + + +-----------+ + | ZOEKGEBIED| + +-----------+ +``` + +Er bestaat geen overlap tussen beide geometrieën. + +--- + +## S_OVERLAPS + +Zoek woonplaatsen die het zoekgebied gedeeltelijk overlappen. + +```cql +S_OVERLAPS( + geometry, + POLYGON(( + 5.04 52.10, + 5.05 52.10, + 5.05 52.11, + 5.04 52.11, + 5.04 52.10 + )) +) +``` + +Visualisatie: + +```text + ######## ++-------------------+ +| ##### | +| ##### | ++-------------------+ +``` + +Een deel van de woonplaats ligt binnen het gebied en een deel erbuiten. + +--- + +## S_CROSSES + +Zoek woonplaatsen die door een lijn worden gekruist. + +```cql +S_CROSSES( + geometry, + LINESTRING( + 5.035 52.095, + 5.055 52.115 + ) +) +``` + +Visualisatie: + +```text +\ + \ + \ ++-------------------+ +| \ | +| \ | ++---\---------------+ + \ + \ +``` + +Deze operator wordt vaak gebruikt bij analyses met wegen, waterlopen of spoorlijnen. + +--- + +## S_EQUALS + +Zoek woonplaatsen waarvan de geometrie exact gelijk is aan de opgegeven geometrie. + +```cql +S_EQUALS( + geometry, + POLYGON(( + 5.04 52.10, + 5.05 52.10, + 5.05 52.11, + 5.04 52.11, + 5.04 52.10 + )) +) +``` + +De begrenzing van de woonplaats moet exact overeenkomen met de opgegeven polygoon. + +--- + +## Spatial operators combineren met attributen + +Ruimtelijke filters kunnen worden gecombineerd met attribuutfilters. + +Voorbeeld: + +```cql +S_INTERSECTS( + geometry, + POLYGON(( + 4.29 52.07, + 4.31 52.07, + 4.31 52.08, + 4.29 52.08, + 4.29 52.07 + )) +) +AND naam='Den Haag' +``` + +Hiermee worden alleen woonplaatsen gezocht die: + +1. het zoekgebied raken; +2. de naam `Den Haag` hebben. + +--- + +## Praktijkvoorbeeld BAG Woonplaats + +De Woonplaats-collectie bevat de geometrische begrenzingen van woonplaatsen. Daardoor is deze collectie bijzonder geschikt voor het demonstreren van ruimtelijke operatoren. + +Bijvoorbeeld: + +```http +https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/woonplaats/items? +filter=S_INTERSECTS(geometry,POLYGON((4.29 52.07,4.31 52.07,4.31 52.08,4.29 52.08,4.29 52.07))) +``` + +Deze query retourneert woonplaatsen die het opgegeven gebied geheel of gedeeltelijk overlappen. + +--- + +## Samenvatting + +Spatial operators beschrijven een ruimtelijke relatie tussen een object en een geometrie. + +| Operator | Betekenis | +|-----------|-----------| +| S_INTERSECTS | raakt of overlapt | +| S_DISJOINT | volledig gescheiden | +| S_TOUCHES | raakt de grens | +| S_WITHIN | ligt volledig binnen | +| S_CONTAINS | bevat volledig | +| S_OVERLAPS | overlapt gedeeltelijk | +| S_CROSSES | kruist | +| S_EQUALS | exact dezelfde geometrie | + +Controleer altijd eerst het conformance-endpoint van een OGC API om te bepalen welke spatial operators ondersteund worden. De BAG OGC API publiceert hiervoor de spatial conformance classes `basic-spatial-functions`, `basic-spatial-functions-plus` en `spatial-functions`. \ No newline at end of file From c6f8277ca9093068043b65ac1989af7791ac88b9 Mon Sep 17 00:00:00 2001 From: John Schaap Date: Thu, 27 Aug 2026 15:28:26 +0200 Subject: [PATCH 4/6] formatting --- docs/features/Ruimtelijke filtering met CQL2.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/features/Ruimtelijke filtering met CQL2.md b/docs/features/Ruimtelijke filtering met CQL2.md index 20d8c35..28d5583 100644 --- a/docs/features/Ruimtelijke filtering met CQL2.md +++ b/docs/features/Ruimtelijke filtering met CQL2.md @@ -9,7 +9,7 @@ Na het doorlopen van deze module kun je: - ruimtelijke relaties beschrijven met CQL2 spatial operators; - bepalen welke spatial operators door een OGC API worden ondersteund; - ruimtelijke filters combineren met attribuutfilters; -- spatial operators toepassen op de BAG Woonplaats-collectie. +- spatial operators toepassen op de BAG Woonplaats-collectie. --- @@ -33,7 +33,7 @@ Soms wil je echter een specifiekere ruimtelijke relatie beschrijven: - Welke woonplaatsen overlappen een gebied? - Welke woonplaatsen liggen volledig buiten een gebied? -Voor deze situaties ondersteunt de BAG OGC API ruimtelijke functies via CQL2. +Voor deze situaties ondersteunt de BAG OGC API ruimtelijke functies via CQL2. --- @@ -47,7 +47,7 @@ Voor de BAG API: https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/conformance ``` -Op de conformance-pagina zijn onder meer de volgende conformance classes aanwezig: +Op de conformance-pagina zijn onder meer de volgende conformance classes aanwezig: ```text basic-spatial-functions @@ -55,7 +55,7 @@ basic-spatial-functions-plus spatial-functions ``` -Deze conformance classes geven aan dat ruimtelijke CQL2-functies ondersteund worden. +Deze conformance classes geven aan dat ruimtelijke CQL2-functies ondersteund worden. --- @@ -377,7 +377,7 @@ Deze query retourneert woonplaatsen die het opgegeven gebied geheel of gedeeltel Spatial operators beschrijven een ruimtelijke relatie tussen een object en een geometrie. | Operator | Betekenis | -|-----------|-----------| +| ----------- | ----------- | | S_INTERSECTS | raakt of overlapt | | S_DISJOINT | volledig gescheiden | | S_TOUCHES | raakt de grens | @@ -387,4 +387,4 @@ Spatial operators beschrijven een ruimtelijke relatie tussen een object en een g | S_CROSSES | kruist | | S_EQUALS | exact dezelfde geometrie | -Controleer altijd eerst het conformance-endpoint van een OGC API om te bepalen welke spatial operators ondersteund worden. De BAG OGC API publiceert hiervoor de spatial conformance classes `basic-spatial-functions`, `basic-spatial-functions-plus` en `spatial-functions`. \ No newline at end of file +Controleer altijd eerst het conformance-endpoint van een OGC API om te bepalen welke spatial operators ondersteund worden. De BAG OGC API publiceert hiervoor de spatial conformance classes `basic-spatial-functions`, `basic-spatial-functions-plus` en `spatial-functions`. From c17eb32289fdc4f6b16240c5feb39138b6d6dace Mon Sep 17 00:00:00 2001 From: John Schaap Date: Fri, 28 Aug 2026 11:06:43 +0200 Subject: [PATCH 5/6] typo's en formatering --- .../CQL-filtering met de BAG OGC API.md | 57 +++++++++---------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/docs/features/CQL-filtering met de BAG OGC API.md b/docs/features/CQL-filtering met de BAG OGC API.md index fd257f2..81052ca 100644 --- a/docs/features/CQL-filtering met de BAG OGC API.md +++ b/docs/features/CQL-filtering met de BAG OGC API.md @@ -44,18 +44,19 @@ Een eenvoudige query ziet er als volgt uit: https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items?filter=postcode='2513 AA' ``` -Deze aanvraag retourneert helaas geen adressen, probeer het nogmaals zonder spatie in de postcode: +Deze aanvraag retourneert helaas geen adressen. Probeer het nogmaals zonder spatie in de postcode: ```http -https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items?filter=postcode='2513 AA' +https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items?filter=postcode='2513AA' ``` -Deze retoneert uitsluitend adressen met postcode 2513 AA +Deze retourneert uitsluitend adressen met postcode 2513 AA. + +**:arrow_right: Vraag waarom werkt de eerste query niet en zonder spaties wel?** -**:arrow_right: Vraag waarom werkt de eerst query niet en zonder spaties wel?** ??? success "Bekijk het antwoord" -In deze dataset is de postcode opgeslagen zonder spatie. Het SQL filter werkt direct op de waardes in de dataset. Een waarde voor postcode met spaties komt niet voor. + In deze dataset is de postcode opgeslagen zonder spatie. Het CQL-filter werkt direct op de waarden in de dataset. Een waarde voor postcode met spaties komt niet voor. --- @@ -90,7 +91,9 @@ of: ...?filter=woonplaats_naam='Den Haag' ``` -Het concept *queryables* is belangrijk omdat niet ieder attribuut automatisch filterbaar is. Door de queryables van een collectie te raadplegen weet je welke eigenschappen door de API worden ondersteund voor filtering. Bij een OGC API Features-service kunnen queryables opgevraagd worden via het endpoint: +Het concept *queryables* is belangrijk omdat niet ieder attribuut automatisch filterbaar is. Door de queryables van een collectie te raadplegen weet je welke eigenschappen door de API worden ondersteund voor filtering. + +Bij een OGC API Features-service kunnen queryables opgevraagd worden via het endpoint: ```text /collections/{collectionId}/queryables @@ -102,8 +105,7 @@ Voor de BAG-adrescollectie is dat: https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/queryables ``` -Een goede werkwijze is om eerst de queryables te bekijken en daarna pas CQL-filters op te stellen. Zo voorkom je dat filters verwijzen naar velden die niet door de API ondersteund worden. Bij PDOK worden deze velden ook getoond onder - +Een goede werkwijze is om eerst de queryables te bekijken en daarna pas CQL-filters op te stellen. Zo voorkom je dat filters verwijzen naar velden die niet door de API ondersteund worden. Bij PDOK worden deze velden ook getoond via het queryables-endpoint van de collectie. ### Beschikbare mogelijkheden in een OGC API "Conformance Classes" @@ -133,7 +135,7 @@ Wanneer je de conformance-pagina bekijkt zie je onder andere dat deze service on Dat betekent onder meer dat: | Conformance class | Betekenis | -| ------------------ | ----------- | +|-----------|-----------| | `filter` | De API ondersteunt filteren van features. | | `features-filter` | Filters kunnen worden toegepast op een featurecollectie. | | `queryables` | De API publiceert welke attributen filterbaar zijn. | @@ -145,6 +147,8 @@ Dat betekent onder meer dat: Voordat je geavanceerde filters gaat gebruiken is het daarom verstandig om eerst het **conformance-endpoint** te bekijken. Daar kun je controleren welke onderdelen van CQL en OGC API Features door de betreffende service worden ondersteund. +--- + ## Exacte vergelijkingen ### Gelijk aan @@ -188,7 +192,7 @@ Voor numerieke velden kunnen standaard vergelijkingsoperatoren worden gebruikt. ### Beschikbare operatoren | Operator | Betekenis | -| ----------- | ----------- | +|-----------|-----------| | = | gelijk aan | | <> | ongelijk aan | | < | kleiner dan | @@ -242,7 +246,7 @@ Zoek alle straatnamen die beginnen met "Snel": Veelgebruikte wildcards: | Wildcard | Betekenis | -| ----------- | ----------- | +|-----------|-----------| | % | nul of meer tekens | | _ | exact één teken | @@ -282,9 +286,7 @@ CQL kan gecombineerd worden met een ruimtelijke filter. Zoek adressen binnen een bepaald gebied én in Appingedam: ```http -https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items? -bbox=6.82,53.31,6.85,53.33& -filter=woonplaats_naam='Appingedam' +https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items?bbox=6.82,53.31,6.85,53.33&filter=woonplaats_naam='Appingedam' ``` Hiermee worden eerst objecten binnen de opgegeven bounding box geselecteerd. Vervolgens wordt de CQL-filter toegepast. @@ -338,7 +340,7 @@ woonplaats_naam = 'Appingedam' wordt: ```text -woonplaats_naam%20%3D%20'Appingedam' +woonplaats_naam%20%3D%20%27Appingedam%27 ``` De meeste HTTP-clients en GIS-tools verzorgen dit automatisch. @@ -354,8 +356,7 @@ Maak een query die alle adressen in Appingedam retourneert. ??? success "Antwoord" ```http - https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items? - filter=woonplaats_naam='Appingedam' + https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items?filter=woonplaats_naam='Appingedam' ``` --- @@ -367,8 +368,7 @@ Maak een query die alle adressen met postcode `9901AA` retourneert. ??? success "Antwoord" ```http - https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items? - filter=postcode='9901AA' + https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items?filter=postcode='9901AA' ``` --- @@ -380,8 +380,7 @@ Maak een query die alle adressen met een huisnummer groter dan 50 retourneert. ??? success "Antwoord" ```http - https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items? - filter=huisnummer > 50 + https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items?filter=huisnummer>50 ``` Hierbij wordt het queryable `huisnummer` gebruikt in combinatie met de operator `>`. @@ -395,8 +394,7 @@ Maak een query die alle adressen retourneert waarvan de straatnaam begint met `S ??? success "Antwoord" ```http - https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items? - filter=openbare_ruimte_naam LIKE 'Snel%' + https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items?filter=openbare_ruimte_naam LIKE 'Snel%' ``` De wildcard `%` betekent: nul of meer willekeurige tekens. @@ -410,9 +408,7 @@ Combineer een `bbox` met een CQL-filter op woonplaats. ??? success "Antwoord" ```http - https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items? - bbox=6.82,53.31,6.85,53.33& - filter=woonplaats_naam='Appingedam' + https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items?bbox=6.82,53.31,6.85,53.33&filter=woonplaats_naam='Appingedam' ``` Eerst worden de adressen binnen de bounding box geselecteerd. @@ -427,13 +423,14 @@ Zoek alle adressen van het Binnenhof in Den Haag met postcode `2513AA`. ??? success "Antwoord" ```http - https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items? - filter=postcode='2513AA' + https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items?filter=postcode='2513AA' ``` Probeer deze query uit te breiden met een extra filter op `openbare_ruimte_naam` of `huisnummer`. +--- + **Toelichting** In deze query worden twee filters gecombineerd: @@ -441,6 +438,4 @@ In deze query worden twee filters gecombineerd: 1. De `bbox` beperkt de resultaten tot een geografisch gebied. 2. De CQL-expressie selecteert alleen adressen waarvan de woonplaats `Appingedam` is. -Daardoor worden uitsluitend adressen binnen het opgegeven gebied én in Appingedam geretourneerd. - ---- +Daardoor worden uitsluitend adressen binnen het opgegeven gebied én in Appingedam geretourneerd. \ No newline at end of file From 02a57138a1038a3aef856391800ed7bb8143e96d Mon Sep 17 00:00:00 2001 From: John Schaap Date: Fri, 28 Aug 2026 13:24:21 +0200 Subject: [PATCH 6/6] url encoding toegevoegd --- .../CQL-filtering met de BAG OGC API.md | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/docs/features/CQL-filtering met de BAG OGC API.md b/docs/features/CQL-filtering met de BAG OGC API.md index 81052ca..b853a6d 100644 --- a/docs/features/CQL-filtering met de BAG OGC API.md +++ b/docs/features/CQL-filtering met de BAG OGC API.md @@ -135,7 +135,7 @@ Wanneer je de conformance-pagina bekijkt zie je onder andere dat deze service on Dat betekent onder meer dat: | Conformance class | Betekenis | -|-----------|-----------| +| ----------- | ----------- | | `filter` | De API ondersteunt filteren van features. | | `features-filter` | Filters kunnen worden toegepast op een featurecollectie. | | `queryables` | De API publiceert welke attributen filterbaar zijn. | @@ -147,6 +147,24 @@ Dat betekent onder meer dat: Voordat je geavanceerde filters gaat gebruiken is het daarom verstandig om eerst het **conformance-endpoint** te bekijken. Daar kun je controleren welke onderdelen van CQL en OGC API Features door de betreffende service worden ondersteund. +### URL encoding + +Wanneer een filter speciale tekens bevat, zoals spaties, aanhalingstekens of een procentteken (`%`), moeten deze in de URL worden gecodeerd. Dit noemen we *URL encoding*. + +Bijvoorbeeld: + +```text +filter=openbare_ruimte_naam LIKE 'Snel%' +``` + +wordt: + +```text +filter=openbare_ruimte_naam%20LIKE%20%27Snel%25%27 +``` + +Veelgebruikte coderingen zijn: `spatie = %20`, `' = %27` en `% = %25` +meer informatie over deze manier van encoding is te vinden op de [wikipedia pagina Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding) --- ## Exacte vergelijkingen @@ -192,7 +210,7 @@ Voor numerieke velden kunnen standaard vergelijkingsoperatoren worden gebruikt. ### Beschikbare operatoren | Operator | Betekenis | -|-----------|-----------| +| ----------- | ----------- | | = | gelijk aan | | <> | ongelijk aan | | < | kleiner dan | @@ -246,7 +264,7 @@ Zoek alle straatnamen die beginnen met "Snel": Veelgebruikte wildcards: | Wildcard | Betekenis | -|-----------|-----------| +| ----------- | ----------- | | % | nul of meer tekens | | _ | exact één teken | @@ -394,9 +412,11 @@ Maak een query die alle adressen retourneert waarvan de straatnaam begint met `S ??? success "Antwoord" ```http - https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items?filter=openbare_ruimte_naam LIKE 'Snel%' + https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items?filter=openbare_ruimte_naam+LIKE+%27Snel%25%27 ``` + https://api.pdok.nl/kadaster/bag/ogc/v2-preprod/collections/adres/items?crs=http%3A%2F%2Fwww.opengis.net%2Fdef%2Fcrs%2FOGC%2F1.3%2FCRS84&limit=10&filter=openbare_ruimte_naam+LIKE+%27Snel%25%27 + De wildcard `%` betekent: nul of meer willekeurige tekens. --- @@ -438,4 +458,4 @@ In deze query worden twee filters gecombineerd: 1. De `bbox` beperkt de resultaten tot een geografisch gebied. 2. De CQL-expressie selecteert alleen adressen waarvan de woonplaats `Appingedam` is. -Daardoor worden uitsluitend adressen binnen het opgegeven gebied én in Appingedam geretourneerd. \ No newline at end of file +Daardoor worden uitsluitend adressen binnen het opgegeven gebied én in Appingedam geretourneerd.