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.
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:
- β Layer source is not PostgreSQL or Spatialite
- β
Layer provider is
ogr(Shapefile, GeoPackage, etc.) - β 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β
| Format | Read | Write | Spatial Index | Performance |
|---|---|---|---|---|
| Shapefile | β | β | β οΈ .qix files | Good |
| GeoPackage | β | β | β R-tree | Excellent |
| GeoJSON | β | β | β | Good |
| KML/KMZ | β | β | β | Good |
| CSV | β | β | β | Fair |
| DXF/DWG | β | β οΈ Limited | β | Fair |
| GPX | β | β | β | Good |
| GML | β | β | β | Good |
| FlatGeobuf | β | β | β Built-in | Excellent |
For optimal performance: GeoPackage or FlatGeobuf (both have spatial indexes)
4. Spatial Predicate Supportβ
OGR backend supports most spatial predicates through QGIS expressions:
| Predicate | Support | Notes |
|---|---|---|
intersects | β Full | Via QGIS expression |
contains | β Full | Via QGIS expression |
within | β Full | Via QGIS expression |
touches | β οΈ Limited | Some formats |
crosses | β οΈ Limited | Some formats |
overlaps | β οΈ Limited | Some formats |
disjoint | β Full | Via QGIS expression |
buffer | β Full | QGIS 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β
- Load any vector layer in QGIS
- Open FilterMate plugin
- Configure filter options
- 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.qixindex - 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)β
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:
- Migrate to PostgreSQL - 10-100x faster
- Use Spatialite - 5-10x faster
- Tile/partition data - split into manageable chunks
Limitationsβ
Compared to Database Backendsβ
| Feature | OGR | Spatialite | PostgreSQL |
|---|---|---|---|
| Max practical size | ~50k features | ~500k features | 10M+ 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:
-
Disable memory layers:
{
"OGR": {
"use_memory_layers": false
}
} -
Switch to GeoPackage format (more efficient)
-
Use PostgreSQL or Spatialite backend instead
Issue: "Filtering very slow"β
Symptom: Takes minutes for small dataset
Solution:
-
Check for spatial index:
# Shapefile - check for .qix file
# GeoPackage - check for rtree table -
Simplify geometry if complex:
processing.run("native:simplifygeometries", {
'INPUT': layer,
'METHOD': 0, # Distance
'TOLERANCE': 1, # meters
'OUTPUT': 'memory:'
}) -
Use simpler predicates -
intersectsfaster thantouches
Issue: "Format not supported"β
Symptom: Cannot open file
Solution:
-
Check GDAL/OGR version:
from osgeo import gdal
print(gdal.VersionInfo()) -
List available drivers:
from osgeo import ogr
for i in range(ogr.GetDriverCount()):
print(ogr.GetDriver(i).GetName()) -
Convert to supported format:
ogr2ogr -f GPKG output.gpkg input.xyz
Format Conversionβ
To GeoPackage (Recommended)β
# 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 Size | Features | OGR (Shapefile) | OGR (GeoPackage) | Spatialite | PostgreSQL |
|---|---|---|---|---|---|
| Small | 5,000 | 0.8s | 0.6s | 0.4s | 0.3s |
| Medium | 50,000 | 25s | 15s | 8.5s | 1.2s |
| Large | 500,000 | Timeout | 180s | 65s | 8.4s |
Format Comparison (50k features):
| Format | Load Time | Filter Time | Total | Spatial Index |
|---|---|---|---|---|
| GeoPackage | 2.3s | 12.7s | 15.0s | β Yes |
| Shapefile + .qix | 3.1s | 21.9s | 25.0s | β Yes |
| Shapefile (no index) | 3.1s | 87.2s | 90.3s | β No |
| GeoJSON | 4.8s | 45.3s | 50.1s | β No |
| KML | 6.2s | 52.7s | 58.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β
- Backends Overview - Multi-backend architecture
- Backend Selection - Automatic selection logic
- PostgreSQL Backend - For best performance
- Spatialite Backend - For medium datasets
- Performance Comparison - Detailed benchmarks
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 filesGPKG- GeoPackageGeoJSON- .geojson, .jsonKML- .kml, .kmzCSV- .csv with geometryGPX- GPS ExchangeDXF- AutoCAD DXFGML- Geography Markup LanguageMemory- In-memory layersFlatGeobuf- .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