Skip to main content
Skip to main content

OGR Backend

The OGR backend provides universal compatibility with all vector formats supported by QGIS through the GDAL/OGR library. It serves as a reliable fallback when PostgreSQL or Spatialite backends are unavailable.

Universal Compatibility

OGR backend works with all vector formats: Shapefiles, GeoPackage, GeoJSON, KML, DXF, CSV, and 80+ more formats.

Overview​

FilterMate's OGR backend uses QGIS's processing framework and memory layers to perform geometric filtering. While not as fast as database backends for large datasets, it provides excellent compatibility and requires no additional setup.

Key Benefits​

  • βœ… Universal format support - works with any OGR-readable format
  • πŸ”§ No setup required - built into QGIS
  • πŸ“¦ Portable - works with local and remote files
  • 🌐 Web formats - GeoJSON, KML, etc.
  • πŸ’Ύ Memory layers - temporary in-memory processing
  • πŸš€ Automatic - fallback when other backends unavailable

When OGR Backend Is Used​

FilterMate automatically selects the OGR backend when:

  1. βœ… Layer source is not PostgreSQL or Spatialite
  2. βœ… Layer provider is ogr (Shapefile, GeoPackage, etc.)
  3. βœ… Fallback when psycopg2 is unavailable for PostgreSQL layers

Common Formats Using OGR Backend:

  • Shapefile (.shp)
  • GeoPackage (.gpkg)
  • GeoJSON (.geojson, .json)
  • KML/KMZ (.kml, .kmz)
  • DXF/DWG (CAD formats)
  • CSV with geometry (.csv)
  • GPS Exchange (.gpx)
  • And 80+ more formats

Installation​

Prerequisites​

  • QGIS 3.x (includes GDAL/OGR)
  • No additional packages needed

Verification​

OGR is always available in QGIS. Check supported formats:

# In QGIS Python Console
from osgeo import ogr

driver_count = ogr.GetDriverCount()
print(f"βœ“ {driver_count} OGR drivers available")

# List some common drivers
for driver_name in ['ESRI Shapefile', 'GPKG', 'GeoJSON', 'KML']:
driver = ogr.GetDriverByName(driver_name)
if driver:
print(f" βœ“ {driver_name}")

Features​

1. Memory Layers​

FilterMate creates memory layers for filtered results:

# Example memory layer created by FilterMate
from qgis.core import QgsVectorLayer

memory_layer = QgsVectorLayer(
f"Point?crs=epsg:4326&field=id:integer&field=name:string",
"filtered_layer",
"memory"
)

# Copy filtered features
for feature in source_layer.getFeatures(expression):
memory_layer.dataProvider().addFeature(feature)

Benefits:

  • Fast creation
  • No disk I/O
  • Automatic cleanup
  • Works with all formats

Limitations:

  • Held in RAM - not suitable for very large datasets
  • Lost when QGIS closes (unless saved)

2. QGIS Processing Framework​

OGR backend leverages QGIS processing algorithms:

# FilterMate uses QGIS processing for complex operations
import processing

result = processing.run("native:extractbyexpression", {
'INPUT': layer,
'EXPRESSION': 'ST_Intersects($geometry, geometry(@filter_layer))',
'OUTPUT': 'memory:'
})

filtered_layer = result['OUTPUT']

Available Operations:

  • Extract by expression
  • Extract by location
  • Buffer
  • Intersection
  • Union
  • Clip
  • And 300+ more algorithms

3. Format Compatibility Matrix​

FormatReadWriteSpatial IndexPerformance
Shapefileβœ…βœ…βš οΈ .qix filesGood
GeoPackageβœ…βœ…βœ… R-treeExcellent
GeoJSONβœ…βœ…βŒGood
KML/KMZβœ…βœ…βŒGood
CSVβœ…βœ…βŒFair
DXF/DWGβœ…βš οΈ Limited❌Fair
GPXβœ…βœ…βŒGood
GMLβœ…βœ…βŒGood
FlatGeobufβœ…βœ…βœ… Built-inExcellent
Best Formats for OGR Backend

For optimal performance: GeoPackage or FlatGeobuf (both have spatial indexes)

4. Spatial Predicate Support​

OGR backend supports most spatial predicates through QGIS expressions:

PredicateSupportNotes
intersectsβœ… FullVia QGIS expression
containsβœ… FullVia QGIS expression
withinβœ… FullVia QGIS expression
touches⚠️ LimitedSome formats
crosses⚠️ LimitedSome formats
overlaps⚠️ LimitedSome formats
disjointβœ… FullVia QGIS expression
bufferβœ… FullQGIS processing

Example:

# QGIS expression for intersects
expression = 'intersects($geometry, geometry(@filter_layer))'

# FilterMate applies to OGR layer
layer.setSubsetString(expression) # If format supports
# OR
filtered_features = [f for f in layer.getFeatures() if expression.evaluate(f)]

Configuration​

Format-Specific Options​

Configure OGR backend behavior in config/config.json:

{
"OGR": {
"use_memory_layers": true,
"enable_spatial_index": true,
"max_features_in_memory": 100000,
"prefer_geopackage": true
}
}

Shapefile Spatial Indexes​

For Shapefiles, create .qix spatial index:

# In QGIS Python Console
layer = iface.activeLayer()
layer.dataProvider().createSpatialIndex()

# Or via processing
processing.run("native:createspatialindex", {
'INPUT': layer
})

This creates myfile.qix next to myfile.shp.

GeoPackage Optimization​

GeoPackage has built-in R-tree indexes:

-- Check spatial index (in GeoPackage)
SELECT * FROM sqlite_master
WHERE type = 'table' AND name LIKE 'rtree_%';

-- Rebuild if needed
DROP TABLE IF EXISTS rtree_my_layer_geometry;
-- QGIS will recreate automatically

Usage​

Basic Filtering​

  1. Load any vector layer in QGIS
  2. Open FilterMate plugin
  3. Configure filter options
  4. Click "Apply Filter"

FilterMate automatically:

  • Detects OGR backend
  • Creates memory layer
  • Copies filtered features
  • Adds layer to QGIS
  • Displays backend indicator: [OGR]

Format Recommendations​

Best Performance:

  • GeoPackage (.gpkg) - has spatial indexes
  • FlatGeobuf (.fgb) - optimized for streaming

Good Performance:

  • Shapefile (.shp) - with .qix index
  • GeoJSON (.geojson) - for smaller datasets

Acceptable Performance:

  • KML (.kml) - for web/Google Earth
  • CSV (.csv) - for simple point data

Slower Performance:

  • DXF/DWG - complex CAD formats
  • Remote services (WFS) - network latency

Saving Filtered Results​

Memory layers are temporary. To persist:

# In QGIS, right-click filtered layer β†’ Export β†’ Save Features As
# Or via code:
from qgis.core import QgsVectorFileWriter

QgsVectorFileWriter.writeAsVectorFormat(
memory_layer,
"/path/to/output.gpkg",
"UTF-8",
layer.crs(),
"GPKG"
)

Performance Tuning​

For Small Datasets (< 10k features)​

  • No special configuration needed
  • All formats work well
  • Memory layers are fast

For Medium Datasets (10k - 50k features)​

  • Use GeoPackage or Shapefile with .qix index
  • Enable memory layers (default)
  • Consider Spatialite backend instead (5x faster)
{
"OGR": {
"use_memory_layers": true,
"enable_spatial_index": true
}
}

For Large Datasets (50k - 500k features)​

Performance Recommendation

Switch to PostgreSQL or Spatialite for 5-10x better performance. OGR backend is not optimal for large datasets.

If must use OGR:

  • Use GeoPackage (best format for large data)
  • Disable memory layers (reduce RAM usage):
    {
    "OGR": {
    "use_memory_layers": false,
    "write_to_disk": true,
    "temp_directory": "/fast/ssd/path"
    }
    }
  • Create spatial indexes
  • Filter in stages if very slow

For Very Large Datasets (> 500k features)​

❌ OGR backend not recommended

Alternatives:

  1. Migrate to PostgreSQL - 10-100x faster
  2. Use Spatialite - 5-10x faster
  3. Tile/partition data - split into manageable chunks

Limitations​

Compared to Database Backends​

FeatureOGRSpatialitePostgreSQL
Max practical size~50k features~500k features10M+ features
Spatial indexes⚠️ Format-dependentβœ… R-treeβœ… GIST
Memory usage⚠️ Highβœ… Lowβœ… Very low
Server-side ops❌ No❌ Noβœ… Yes
Concurrent access⚠️ Limited⚠️ Limitedβœ… Excellent
Query optimization❌ Basicβœ… Goodβœ… Excellent

Format-Specific Limitations​

Shapefile:

  • 2GB file size limit
  • 254 character field name limit
  • No mixed geometry types
  • Date/time limited precision

GeoJSON:

  • No spatial index support
  • Can be very large (verbose format)
  • Slower parsing on large files

KML:

  • Limited attribute support
  • No true spatial operations
  • Better for visualization than analysis

CSV:

  • Geometry stored as WKT (slow parsing)
  • No spatial index
  • Not recommended for large datasets

Troubleshooting​

Issue: "Layer has no spatial index"​

Symptom: Slow queries despite small dataset

Solution:

For Shapefile, create .qix index:

layer.dataProvider().createSpatialIndex()

For GeoPackage, rebuild R-tree:

# Open in DB Manager and run:
# DROP TABLE rtree_layer_name_geometry;
# Then reload layer

Issue: "Out of memory"​

Symptom: QGIS crashes on large dataset

Solution:

  1. Disable memory layers:

    {
    "OGR": {
    "use_memory_layers": false
    }
    }
  2. Switch to GeoPackage format (more efficient)

  3. Use PostgreSQL or Spatialite backend instead

Issue: "Filtering very slow"​

Symptom: Takes minutes for small dataset

Solution:

  1. Check for spatial index:

    # Shapefile - check for .qix file
    # GeoPackage - check for rtree table
  2. Simplify geometry if complex:

    processing.run("native:simplifygeometries", {
    'INPUT': layer,
    'METHOD': 0, # Distance
    'TOLERANCE': 1, # meters
    'OUTPUT': 'memory:'
    })
  3. Use simpler predicates - intersects faster than touches

Issue: "Format not supported"​

Symptom: Cannot open file

Solution:

  1. Check GDAL/OGR version:

    from osgeo import gdal
    print(gdal.VersionInfo())
  2. List available drivers:

    from osgeo import ogr
    for i in range(ogr.GetDriverCount()):
    print(ogr.GetDriver(i).GetName())
  3. Convert to supported format:

    ogr2ogr -f GPKG output.gpkg input.xyz

Format Conversion​

# Command line (ogr2ogr)
ogr2ogr -f GPKG output.gpkg input.shp

# Python
import processing
processing.run("native:package", {
'LAYERS': [layer],
'OUTPUT': '/path/to/output.gpkg'
})

To Shapefile​

ogr2ogr -f "ESRI Shapefile" output.shp input.gpkg

To GeoJSON​

ogr2ogr -f GeoJSON output.geojson input.shp

Performance Benchmarks​

Real-world performance on typical hardware (Core i7, 16GB RAM, SSD):

Dataset SizeFeaturesOGR (Shapefile)OGR (GeoPackage)SpatialitePostgreSQL
Small5,0000.8s0.6s0.4s0.3s
Medium50,00025s15s8.5s1.2s
Large500,000Timeout180s65s8.4s

Format Comparison (50k features):

FormatLoad TimeFilter TimeTotalSpatial Index
GeoPackage2.3s12.7s15.0sβœ… Yes
Shapefile + .qix3.1s21.9s25.0sβœ… Yes
Shapefile (no index)3.1s87.2s90.3s❌ No
GeoJSON4.8s45.3s50.1s❌ No
KML6.2s52.7s58.9s❌ No

Best Practices​

βœ… Do​

  • Use GeoPackage for best OGR performance
  • Create spatial indexes (.qix for Shapefile)
  • Keep datasets < 50k features for OGR backend
  • Use for universal format compatibility
  • Test format conversion if performance is poor

❌ Don't​

  • Don't use OGR for > 100k features - too slow
  • Don't forget spatial indexes - huge performance impact
  • Don't use CSV/GeoJSON for large data - no spatial index
  • Don't rely on Shapefile for production - consider GeoPackage
  • Don't use memory layers for huge datasets - will crash

Migrating to Better Backends​

When to Switch to Spatialite​

Indicators:

  • Dataset > 10k features
  • Need better query performance
  • Want persistent results

Migration:

# Export to Spatialite
from qgis.core import QgsVectorFileWriter

options = QgsVectorFileWriter.SaveVectorOptions()
options.driverName = "SQLite"
options.datasourceOptions = ["SPATIALITE=YES"]

QgsVectorFileWriter.writeAsVectorFormatV3(
layer,
"/path/to/output.sqlite",
QgsCoordinateTransformContext(),
options
)

When to Switch to PostgreSQL​

Indicators:

  • Dataset > 50k features
  • Need concurrent access
  • Want server-side operations
  • Need best performance

Migration:

# Using ogr2ogr
ogr2ogr -f PostgreSQL \
PG:"host=localhost dbname=mydb user=myuser" \
input.gpkg \
-lco GEOMETRY_NAME=geometry \
-lco SPATIAL_INDEX=GIST

See Also​

Technical Details​

Memory Layer Creation​

# FilterMate creates memory layers like this
from qgis.core import QgsVectorLayer, QgsFeature

# Create memory layer with same structure
uri = f"{geom_type}?crs={crs_string}"
for field in source_layer.fields():
uri += f"&field={field.name()}:{field.typeName()}"

memory_layer = QgsVectorLayer(uri, "filtered", "memory")

# Copy filtered features
features = []
for feature in source_layer.getFeatures(expression):
features.append(QgsFeature(feature))

memory_layer.dataProvider().addFeatures(features)

Supported OGR Drivers​

Common drivers in QGIS 3.x:

  • ESRI Shapefile - .shp files
  • GPKG - GeoPackage
  • GeoJSON - .geojson, .json
  • KML - .kml, .kmz
  • CSV - .csv with geometry
  • GPX - GPS Exchange
  • DXF - AutoCAD DXF
  • GML - Geography Markup Language
  • Memory - In-memory layers
  • FlatGeobuf - .fgb (streaming format)

Check all available:

from osgeo import ogr
for i in range(ogr.GetDriverCount()):
driver = ogr.GetDriver(i)
print(f"{driver.GetName()}: {driver.GetMetadata().get('DMD_LONGNAME', '')}")

Last Updated: December 8, 2025
Plugin Version: 2.2.3
OGR/GDAL Support: Version included with QGIS 3.x