ResultPaging bij WFS datasets

Ik doe een poging tot het implementeren van ResultPaging in mijn WFS client. Ik test dit momenteel met een aantal datasets van PDOK, waaronder BAG en de kadastrale kaart.

Als referentie gebruik ik de OGC WFS 2.0 specificatie. Daarin wordt result paging behandeld in paragraaf 7.7.4.4.

Als ik het goed begrijp zou de procedure moeten zijn:

  • Check de ImplementsResultPaging waarde van de service capabilities
  • Doe een WFS query waarbij dmv een “count” parameter wordt gehint op dat ik result paging wil gebruiken
  • De resulterende feature set heeft een “next” attibuut met een URL om de volgende pagina op te halen

Waar ik nu tegenaan loop:

  • Niet alle WFS diensten op PDOK geven een “next” URL als ik een count variabele opgeef. Als work-around werkt het om ook “startindex=0” mee te geven.
  • De “next” URL wordt bij een aantal datasets (oa BAG v1_1 en kadastralekaart v4) steeds langer, omdat de server er iedere keer een extra “SERVICE=WFS&” aantoe voegt. Is niet echt een probleem, maar is wel wat rommelig
  • De BAG service geeft bij het in pagina’s inlezen van de resultaten dubbele objecten (en mist er daardoor ook een aantal)

Van dat laatste punt heb ik een voorbeeld:

http://geodata.nationaalgeoregister.nl/bag/wfs/v1_1?REQUEST=GetFeature&SERVICE=WFS&VERSION=2.0.0&OUTPUTFORMAT=application%2Fgml%2Bxml%3B%20version%3D3.2&BBOX=192652.920425,470719.209986,193252.920425,471319.209986&srsName=EPSG:28992&TYPENAMES=bag:pand&count=100&startindex=0

vs

http://geodata.nationaalgeoregister.nl/bag/wfs/v1_1?REQUEST=GetFeature&SERVICE=WFS&VERSION=2.0.0&OUTPUTFORMAT=application%2Fgml%2Bxml%3B%20version%3D3.2&BBOX=192652.920425,470719.209986,193252.920425,471319.209986&srsName=EPSG:28992&TYPENAMES=bag:pand

In beide gevallen krijg ik na het inlezen van de resultatenset 347 objecten. Echter, bij de in stukjes ingelezen resultaten ontbreekt bijvoorbeeld pand “0200100000002048”, maar krijg ik “0200100000711827” dubbel.

Doe ik iets fout met het pagen van resultaten? Wat zou een work-around kunnen zijn?

Hoi @SebastiaanR

We zitten in een “migratie traject”, dit zal over tijd gelijk getrokken worden tussen de verschillende datasets.

We zien het, dit kunnen (mogelijk) ‘eenvoudig’ oplossen.

Dat dit gebeurd met de URL’s die jij gebruikt heeft een technische ‘achtergrond’… als eerste dit is te ‘fixen’ door een SORTBY=bag:identificatie in je QUERY request mee te geven.

Dan krijg je dezelfde output als met een ‘compleet’ request, dus:

http://geodata.nationaalgeoregister.nl/bag/wfs/v1_1?REQUEST=GetFeature&SERVICE=WFS&VERSION=2.0.0&OUTPUTFORMAT=application%2Fgml%2Bxml%3B%20version%3D3.2&BBOX=192652.920425,470719.209986,193252.920425,471319.209986&srsName=EPSG:28992&TYPENAMES=bag:pand

heeft dan hetzelfde resultaat als

http://geodata.nationaalgeoregister.nl/bag/wfs/v1_1?REQUEST=GetFeature&SERVICE=WFS&VERSION=2.0.0&OUTPUTFORMAT=application%2Fgml%2Bxml%3B%20version%3D3.2&BBOX=192652.920425,470719.209986,193252.920425,471319.209986&srsName=EPSG:28992&TYPENAMES=bag:pand&count=100&startindex=0&SORTBY=bag:identificatie
http://geodata.nationaalgeoregister.nl/bag/wfs/v1_1?REQUEST=GetFeature&SERVICE=WFS&VERSION=2.0.0&OUTPUTFORMAT=application%2Fgml%2Bxml%3B%20version%3D3.2&BBOX=192652.920425,470719.209986,193252.920425,471319.209986&srsName=EPSG:28992&TYPENAMES=bag:pand&count=100&startindex=100&SORTBY=bag:identificatie
http://geodata.nationaalgeoregister.nl/bag/wfs/v1_1?REQUEST=GetFeature&SERVICE=WFS&VERSION=2.0.0&OUTPUTFORMAT=application%2Fgml%2Bxml%3B%20version%3D3.2&BBOX=192652.920425,470719.209986,193252.920425,471319.209986&srsName=EPSG:28992&TYPENAMES=bag:pand&count=100&startindex=200&SORTBY=bag:identificatie
http://geodata.nationaalgeoregister.nl/bag/wfs/v1_1?REQUEST=GetFeature&SERVICE=WFS&VERSION=2.0.0&OUTPUTFORMAT=application%2Fgml%2Bxml%3B%20version%3D3.2&BBOX=192652.920425,470719.209986,193252.920425,471319.209986&srsName=EPSG:28992&TYPENAMES=bag:pand&count=100&startindex=300&SORTBY=bag:identificatie

347 objecten, allemaal uniek

Waarom een SORTBY in de query, dit heeft te maken (zoals je mogelijk wel kan voorstellen) dat je niet met 1 server aan het communiceren bent maar met meerdere. Je requesten landen dus op verschillende backends, waardoor de resultset door verschillende cursurs (ongesorteerd) terugkomen. Door dit te ‘escapen’ kan je een SORTBY ‘gebruiken’ wat ervoor zorgt dat ongeacht de backend het resultaat ‘altijd’ in dezelfde volgorde terugkomt en dat iedere backend op de juiste plek ‘inprikt’ om de vraag “count=100&startindex=200” hetzelfde te beantwoorden.

Hoi Wouter,

Bedankt voor je antwoorden!

Ik begrijp wat je hier bedoeld, maar het antwoord is niet helemaal bevredigend :slight_smile:

De OGC WFS2.0 specificaties zegt niks over dat een expliciete sortering nodig zou zijn, en de MapServer referentie (WFS reference — GeoServer 2.26.x User Manual) benoemt zelfs: “There is no obligation to use sortBy with count in a GetFeature request”. Ik had eigenlijk gehoopt/aangenomen dat de service zelf een impliciete (dataset specifieke) volgorde zou forceren bij gebruik van een result paging…

Het expliciet op moeten geven van een sorteer parameter maakt het maken van een generieke WFS client implementatie een stuk lastiger. Kan ik met de DescribeFeature een willekeurige parameter pakken en daar op sorteren voor een concequente sortering (lijkt me niet?), of kan ik bijvoorbeeld op alle velden sorteren om een gegarandeerde volgorde te forceren? En hoe zou dat moeten als ik bijvoorbeeld meerdere featuretypes (waarvan de properties niet overeen komen) in 1 request opvraag? Resulteert dat dan nog steeds in een consequente volgorde?

Hoi @SebastiaanR

Je hebt helemaal gelijk dat de spec daar niet iets ‘expliciet’ over zegt, maar Geoserver (neem aan dat je daar naar refereert, i.p.v. Mapserver ) zegt zelf wel weer expliciet: “There is no obligation to use sortBy with count in a GetFeature request, but they can be used together to manage the returned selection of features more effectively.”

Dus hoe ‘wij’ het interpreteren is dat als het toepassen van een SORTBY in een GetFeature request ‘gewoon’ onderdeel is van de spec. M.a.w. als het gebruik van een SORTBY ‘nodig’ is, is dat ‘normaal’ gebruik van een WFS koppelvlak. (los van het feit dat PDOK meerder instanties draait van ‘dezelfde’ service, waarbij de specificaties noch de implementatie (geoserver, mapserver) ‘rekening’ meehouden…)

Het feit dat de SORTBY een onderdeel is van de spec, geeft aan dat 't iets is waar expliciet opgestuurd kan worden. Dat veel “gebruiker” verwachten dat m.b.t. WFS koppelvlak veel (of alles) voor ze geregeld is is denk een misvatting. In mijn optiek is het niet ‘raar’ dat een afnemer ‘enige’ tuning/uitzoek werk moet doen hoe het ‘efficients’ de service te bevragen. De WFS spec zegt namelijk over de grammatica over hoe je iets ‘kan’ bevragen, maar ‘hoe’ je het bevraagt, de zins opbouw/volgorde (query opbouw, combi parameters, wel/geen sortby, enz…) is iets waar ‘effort’ ingestoken moet worden door de applicatie bouwer

Los van performance, eigenlijk wel ja…

Ja, dat is wat ik probeerde uit te leggen …

Wat is het ‘voorbeeld’ request wat je dan zou willen uitvoeren? Dat geeft wat meer context bij het beantwoorden van je vraag.

Ah, de wondere wereld van ambigue specificaties :slight_smile:

Zoals ik het lees is de sortby parameter optioneel, en had het ook moeten werken zonder.

De OGC WFS specificatie zegt over ordenen ook nog:

7.9.2.5.4.4 Sort processing
A web feature service that receives an ad hoc query expression without a sorting clause, shall generate a response document in which features are presented in whatever order the server chooses. However, to comply with this International Standard, servers shall ensure that whatever order is presented when an ad hoc query, not containing a sort clause, is first executed is preserved across subsequent executions of the same ad hoc query expression on the same set of features.

EXAMPLE A server may choose to sort the features by their gml:id if the client has not specified a specific sorting clause. Subsequent invocations of the same query expression on the same set of data should result in a response document that presents the features in the same order.

en in sectie 7.7.4.4.1:

Upon resolving the previous or next URIs, servers shall either generate a valid response collection containing the next or previous set of features or values

In mijn optiek zouden de “previous” of “next” URI’s dus (ook zonder sortby) de matchende resultaten van dezelfde query expressie moeten opleveren, maar dat kun je idd ook anders lezen.

Stel dat ik expliciet wil sorteren op een query met meerdere featuretypes: na wat experimenteren met de BAG dataset, is jullie syntax daarvoor:
?REQUEST=GetFeature&SERVICE=WFS&VERSION=2.0.0&TYPENAMES=bag:pand,bag:ligplaats&sortby=(gid,identificatie,bouwjaar,status)(gid,identificatie,status,huisnummer)

Die syntax voor SORTBY kan ik niet direct terugvinden in de OGC specificaties (een soortgelijke syntax zie ik bij ALIAS bijv wel terug); is dat een eigen interpretatie, of lees ik ergens overheen?

Als dat namelijk een niet-standaard syntax is, zal ik helaas moeten terugvallen naar losse requests per featuretype om de implementatie compatible te houden. En het hele doel van de query in 1 keer doen en resultpaging toe te passen, was juist om het aantal requests op de server te minimaliseren :confused:

Een observatie: Ik zie geen BBOX/FILTER o.i.d. bij het request om hem strikter te maken. Als het doel is om via de WFS de ‘complete’ BAG binnen te trekken dat is dan niet echt de bedoeling. Daar zijn alternatieve voor o.a. de ATOM http://geodata.nationaalgeoregister.nl/inspireadressen/atom/inspireadressen.xml

Nope, hiervoor zijn we aan ‘implementaties’ overgeleverd zoals Geoserver en Mapserver in ons geval. We hopen hier in de toekomst wel een ‘harmonisatie’ te laten plaatsvinden.

1 request om alles op te halen is vaak voor ons net zo onwenselijk als +10.000.000 (bijv de BAG) om ieder feature op te halen. Dat requesten enigszins ‘opgeknipt’ worden (bijv. per featuretype) is vaak wenselijker om zo een gezonde balans tussen deze 2 uiterste te vinden. Dat het wel kan voor een dataset van een paar 100 objecten, zoals bijv: de natura2000 spreekt voor zich. Gezien we het dan niet over een basisadministratie hebben van miljoenen objecten/features.

De query altijd voorzien van een BBOX! Ik had hem voor de leesbaarheid op het forum en om de syntax van de SORTBY te benadrukken even weggelaten.

Meestal is de BBOX relatief klein (50 a 100m), en valt het aantal teruggegeven features als totale query ruim binnen de 1000 die jullie standaard als maximaal aantal resultaten terug geven (CountDefault). Mijn gebruik van resultpaging is bedoeld als fall-back voor de incidentele gevallen dat het totaal aantal features wel over de 1000 gaat.

Is het altijd beter om per featuretype te querieen? Zijn bijv 4 losse queries met enkele resultaten efficiënter dan een samengestelde query?

Helemaal goed dan!

Vanuit ons perspectief (en edge-cases daargelaten): Ja

  • M.b.t. performance (en zo nodig mogelijk technische “obstakels”) van onze kant is dat “beter” om per featuretype te bevragen. Vanaf een ‘client’ side kan je dan ook ‘sneller’ maken door X streams/calsl parallel uit te voeren i.p.v. sequentieel (wat automatisch server-side op de servers gebeurd)
  • Tevens hoewel het “meer” queries zijn, zijn de queries ‘minder’ complex m.b.t. de vertaling naar SQL, er hoeven dan geen JOIN(s) en UNION(s) plaats te vinden.

Kort door de bocht: “Hoe simpeler, hoe sneller”. Dit is namelijk ook de enige “use-case” waarop wij kunnen tunen (,waar “iedereen” profijt bij heeft). Dus specifieke requesten op ID’s en BBOX’en, m.a.w. dus wat/welk object (ID) en waar ligt iets (BBOX/GEOM) Dit zijn ook 95% (als 't niet meer is) van de requesten die wij verwerken.

Bij al het andere is het verstandig (voor een applicatie bouwer) om na te gaan welke “verantwoordelijkheid” van de applicatie hij bij een (externe)service wil neerleggen. Schuift een developer een groot deel van de logica naar onze services, (iets wat wij niet weten,… is er überhaupt een contract…?) dan kan er door nieuwe datamodelen/koppelvlakken/uitfaseringen/enz… ‘dingen’ kapot gaan. Als dat belangrijk is voor een developer dan is het vaak verstandiger om specifieke applicatie logical in z’n eigen applicaties te trekken en het zo in z’n eigen invloedssfeer te hebben. Zodat het ene ‘domme doorgeefluikje’ ‘eenvoudig’ vervangen kan worden door het andere.