18

How to get features by their attributes (similar to 'IQueryFilter' in ArcObjects) in QGIS using Python? Instead of getting all features and filter it manually, is there any option to use where clause to filter it out?

Example: I have a field name called "Counties". It has more than fifty thousand of features i.e not possible to fetch all features and filter it because of time consuming. So i can query it by using iqueryfilter.whereclause = 'Counties = Norwich' in ArcObjects. Similar thing I need in PyQGIS.

3
  • 1
    @NathanW yes you are correct. i need only return the data using a query from the layer. could you please provide me any example in pyqgis?
    – venkat
    Commented Apr 22, 2013 at 9:52
  • @NathanW Hi i got it. its working like definition query in arcgis. see this example. t = outputLayer.setSubsetString('UniqID = ' + inputFeat.attribute("UniqID").toPyObject()) if t == True: outputProvider = outputLayer.dataProvider() print outputProvider.featureCount() i.e. it will only return the query satisfied data
    – venkat
    Commented Apr 23, 2013 at 4:29
  • @venkat where in QGIS are you putting the query? Thanks.
    – ianbroad
    Commented Jul 21, 2013 at 13:52

4 Answers 4

15

You can simply do:

features = l.getFeatures('"Counties" = \'Norwich\'')

The QGIS expression engine is also able to do this using the QgsFeatureRequest.setFilterExpression(str) method (Since QGIS 2.2)

request = QgsFeatureRequest().setFilterExpression( '"Counties" = \'Norwich\'' )
it = l.getFeatures( request )

Starting with QGIS 2.10 it is even possible that filtering in such a way will give you some extra performance over other types of filtering (like python implementations).

Basically this applies if the following three conditions are met:

  • You are using a layer with the postgis provider At the moment (2.16) many more than just postgis provider implement this (spatialite, ogr, oracle...).
  • Your expression is not overly complicated (things like >, =, IN, NOT NULL ... are supported)
  • You have enabled this feature in Settings > Options > Data Sources > Data Source Handling > Execute expression on postgres server-side
  • The performance benefit is optimal with appropriate indexes on the database tables
1

This post - which could be considered an answer to a duplicate question - details how to fetch all attributes from a layer. The author describes the process you are looking for as filtering the data manually once it is returned. It's a pretty complete reference and their link should really help you out.

1
  • 2
    This not a duplicate question. i dont want to fetch all attributes from a layer. Filter it first and then i want to fetch the features which are come under the filter criteria. i.e the performance is much better.
    – venkat
    Commented Apr 22, 2013 at 9:37
1

By using a sql query it also easily possible with ogr. You could execute this code for instance in the QGIS python console or a standalone script.
Example:

from osgeo import ogr

path = "path to your shapefile.shp"
ID = "FieldID" # For instance 'Countries' 
datasource = ogr.Open(str(path)) # your datasource

layer = datasource.GetLayer(0) # Import layer 0 --> only works with shapefiles
layerName = str( layer.GetName() )# Save the Layersname first

# Do the sql query
# Selects all features from a layer datasource where Field Countries is equal to 'Germany'
layers = datasource.ExecuteSQL("SELECT * FROM %s WHERE %s = '%s'" % (layerName, ID, 'Germany') )
res = []
for i in range(0,layers.GetFeatureCount()):
   f = layers.GetFeature(i)
   g = f.GetGeometryRef()
   res.append(g.Area()) 

# res now contains the measured area of each feature where the attribute ID has the value 'Germany'
0

Specifying SQL filters are not yet supported using QGIS API as of version 1.9.

As I understand from this mailing list article, support for "native provider's SQL" would only be in a future release.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.