Using Parameters in GeoServer Views

 This method is great when trying to serve a layer with a lot of detailed features that covers a large area, like land parcels.

Instead of getting the full layer for your web map, you can just limit visibility of the layer for specific zoom levels and query the view as GeoJSON whenever the user finishes moving within those zoom levels.
I added some sample leaflet code for updating your layer every move or zoom end at the bottom, but that's not the main part of this piece.

 

How It's Done?

Creating A View Layer In GeoServer

When creating a new layer from a PostGIS datastore  you have the option toConfigure a new SQL view.
This will let you define a SQL query from PostGIS that will generate your new layer.



 

 

 

This can be used for a simple query in you want to just show a part of your layer, whether showing some of the columns or using the where clause to show just part of the rows. This view can be something permanent that updates itself whenever the database gets updates OR you can use parameters to query which allow you to use thing like:

1. Using a bound box to query the layer

2. Using geometry from another layer to query your layer

3. Using text to select specific attributes.



You can limit the parameters with regex (which can be both very specific and a bit uncomfortable), in this example I'll use the regex validation to get only floats in all my parameters.

You can practice using regex on sites like https://regexr.com/ which also explains what you are doing, and what you are doing wrong.


Adding Parameters To The Query

To add a parameter within your query you can simply add the parameter name between precent signs (%) like so:





Validating The Parameters

If I wanted to limit my ID parameter just to positive or negative numbers, than the regex validtion expression will be something like this:

    ^-?[\d.]+$   

 

 

Getting The Features within Bounding Box

 To limit the features from my layer to operate within the bounding box, we need 8 parameters, which are actually 4 sets of coordinates, the last set we'll need to repeat since polygons need the first and last coordinate to be the same.

Our query will look something like this:

SELECT id,
       geom
FROM buildings
WHERE ST_Within(geom, ST_GeomFromText('POLYGON((%X1% %Y1%,
                                                %X2% %Y2%,
                                                %X3% %Y3%,
                                                %X4% %Y4%,
                                                %X1% %Y1%))'4326))

With this query I can query which features in my layer are within (not intersecting) my web map's bounding box.




 

To use multiple parameters in the query url we'll use the viewparams key and seperate the parameters with ';'. for more info on querying A GeoServer layer as WFS GeoJSON look at the leaflet example.

GeoServer Views can be powerfull tools, combining GeoServer's ease of access and verstility for publishing spatial data and PostGIS' powerfull processing into one easy to use tool with GeoServer acting as another gateway to your PostGIS data.


Leaflet Example

function updateLayer(){
    zoom = map.getZoom()
    
    bounds = map.getBounds()
    rectangle = L.rectangle(bounds)
    coords = rectangle.toGeoJSON().geometry.coordinates[0]

    if(zoom >= 14){

        queryUrl = `http://${gsip}:${gsport}/geoserver/${workspace}/\
        ows?service=WFS&version=1.0.0&request=GetFeature&typeName=\
        ${workspace}:${layer}&outputFormat=application%2Fjson&\
        viewparams=X1:${coords[0][0]};\
                    Y1:${coords[0][1]};\
                    X2:${coords[1][0]};\
                    Y2:${coords[1][1]};\
                    X3:${coords[2][0]};\
                    Y3:${coords[2][1]};\
                    X4:${coords[3][0]};\
                    Y4:${coords[3][1]}`
        $.getJSON(queryUrl,function(response){
            parcelData = response;
            if(map.hasLayer(parcels)){map.removeLayer(parcels)}
            
            parcelsL.geoJson(parcelData ).addTo(map)
        })
     }
map.on('zoomend',updateLayer)
map.on('moveend',updateLayer)

Comments