Learn how to execute a SQL query to return features from a feature layer based on spatial and attribute criteria.
A feature layer can contain a large number of features stored in ArcGIS. You can query a layer to access a subset of its features using any combination of spatial and attribute criteria. You can control whether or not each feature's geometry is returned, as well as which attributes are included in the results. Queries allow you to return a well-defined subset of your hosted data for analysis or display in your app.
In this tutorial, you'll write code to perform SQL queries that return a subset of features in the LA County Parcel feature layer (containing over 2.4 million features). Features that meet the query criteria are selected in the map.
Prerequisites
The following are required for this tutorial:
- An ArcGIS account to access API keys. If you don't have an account, sign up for free.
- Your system meets the system requirements.
- The ArcGIS Maps SDK for Qt, version 200.4.0 or later is installed.
- The Qt 6.5.1 software development framework is installed.
Steps
Open the project in Qt Creator
-
To start this tutorial, complete the Display a map tutorial or download and unzip the solution.
-
Open the display_a_map project in Qt Creator.
-
If you downloaded the Display a map solution, set your API key.
An API Key enables access to services, web maps, and web scenes hosted in ArcGIS Online.
-
Go to your developer dashboard to get your API key. For these tutorials, use your default API key. It is scoped to include all of the services demonstrated in the tutorials.
-
In the Projects window, in the Sources folder, open the main.cpp file.
-
Modify the code to set the API key. Paste the API key, acquired from your dashboard, between the quotes. Then save and close the file.
main.cppUse dark colors for code blocks Change line // 2. API key authentication: Get a permanent key that gives your application access to Esri // location services. Create a new API key or access existing API keys from // your ArcGIS for Developers dashboard (https://links.esri.com/arcgis-api-keys). const QString apiKey = QString("");
-
Update the header file
This app will use various functions and member variables that need to be declared in the header file.
-
In Projects, double-click Headers > Display_a_map.h to open the file.
-
Forward declare the following classes.
Display_a_map.hUse dark colors for code blocks namespace ArcGISRuntime { class Map; class MapQuickView; class FeatureLayer; class ServiceFeatureTable;
-
Add the following code to define a function called
run
that will be invokable from the GUI.Query Display_a_map.hUse dark colors for code blocks public: explicit Display_a_map(QObject* parent = nullptr); ~Display_a_map() override; Q_INVOKABLE void runQuery(const QString& expression);
-
Declare the following private function and member variables. Then save and close the file.
Display_a_map.hUse dark colors for code blocks private: Esri::ArcGISRuntime::MapQuickView* mapView() const; void setMapView(Esri::ArcGISRuntime::MapQuickView* mapView); void setupViewpoint(); void addFeatureLayer(); Esri::ArcGISRuntime::FeatureLayer* m_featureLayer = nullptr; Esri::ArcGISRuntime::ServiceFeatureTable* m_featureTable = nullptr;
Include header files in the source code
To create this app you will need to include several class header files from the ArcGIS Maps Qt C++ API.
-
In Projects, double-click Sources > Display_a_map.cpp to open the file.
-
Add the following include statements. Each of these classes are needed for this tutorial.
Display_a_map.cppUse dark colors for code blocks #include "Display_a_map.h" #include "Map.h" #include "MapTypes.h" #include "MapQuickView.h" #include "Point.h" #include "Viewpoint.h" #include "SpatialReference.h" #include <QFuture> #include "Envelope.h" #include "Feature.h" #include "FeatureLayer.h" #include "LayerListModel.h" #include "FeatureIterator.h" #include "FeatureQueryResult.h" #include "QueryParameters.h" #include "SelectionProperties.h" #include "ServiceFeatureTable.h" #include <memory> #include <QColor> #include <QList> #include <QUuid> #include <QUrl>
Add a feature layer, query features, and select results
You will add three functions to add a feature layer from ArcGIS online, execute a query of that layer, and create a features list from the query result.
-
Add code to create the
add
function. This function adds the LA_County_Parcels feature layer hosted on ArcGIS Online to the map.Feature Layer Display_a_map.cppUse dark colors for code blocks void Display_a_map::setupViewpoint() { const Point center(-118.80543, 34.02700, SpatialReference::wgs84()); const Viewpoint viewpoint(center, 100000.0); m_mapView->setViewpointAsync(viewpoint); } void Display_a_map::addFeatureLayer() { // Create a ServiceFeatureTable from a QUrl. m_featureTable = new ServiceFeatureTable(QUrl("https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/LA_County_Parcels/FeatureServer/0"), this); // Create the feature layer using the feature table. m_featureLayer = new FeatureLayer(m_featureTable, this); // Add the feature layer to the map. m_map->operationalLayers()->append(m_featureLayer); }
-
Add the following function to implement the query. The
run
function executes a query of the parcels layer. This function creates aQuery QueryParameters
object that includes the currently visible map extent and a SQL expression, and then executes the query on the parcels table. When a query completes, the code iterates the returned results and adds those features to a list. That list is then used to select features in the parcels layer.Display_a_map.cppUse dark colors for code blocks void Display_a_map::addFeatureLayer() { // Create a ServiceFeatureTable from a QUrl. m_featureTable = new ServiceFeatureTable(QUrl("https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/LA_County_Parcels/FeatureServer/0"), this); // Create the feature layer using the feature table. m_featureLayer = new FeatureLayer(m_featureTable, this); // Add the feature layer to the map. m_map->operationalLayers()->append(m_featureLayer); } void Display_a_map::runQuery(const QString& expression) { if (!m_featureTable) return; // Create a query parameter object and set the WhereClause. QueryParameters queryParams; queryParams.setGeometry(m_mapView->currentViewpoint(ViewpointType::BoundingGeometry).targetGeometry().extent()); queryParams.setWhereClause(expression); m_featureTable->queryFeaturesAsync(queryParams).then(this,[this](FeatureQueryResult* rawQueryResult) { if (!rawQueryResult) return; // Wrap the FeatureQueryResult in a unique_ptr to manage the memory effectively. auto queryResult = std::unique_ptr<FeatureQueryResult>(rawQueryResult); // Clear any existing selection. m_featureLayer->clearSelection(); QList<Feature*> features; // Iterate over the result object. while(queryResult->iterator().hasNext()) { Feature* feature = queryResult->iterator().next(this); // Add each feature to the list. features.append(feature); } // Select features. m_featureLayer->selectFeatures(features); }); }
-
By default, selected features in the map view are displayed in cyan. Modify the
set
function to call your new function and also set the color for displaying selected parcel layer features (or any other selection) in your map view. Then save the file.M a p View Display_a_map.cppUse dark colors for code blocks // Set the view (created in QML) void Display_a_map::setMapView(MapQuickView* mapView) { if (!mapView || mapView == m_mapView) { return; } m_mapView = mapView; m_mapView->setMap(m_map); addFeatureLayer(); m_mapView->setSelectionProperties(SelectionProperties(QColor(Qt::yellow)));
Show a list of query expressions for the user to choose from
You will create a UI that allows the user to choose from a list of predefined query expressions. The expressions are presented in a Combo
control and when the user makes a choice, the expression is passed to the run
method to find parcels that meet the selected criterion within the currently visible map extent.
-
In Projects, double-click Resources > qml\qml.qrc/qml/Display_a_mapForm.qml to open the file.
-
Add the following code to create a
Combo
control to execute a predefined query expression.Box Display_a_mapForm.qmlUse dark colors for code blocks // Declare the C++ instance that creates the map etc., and supply the view. Display_a_map { id: model mapView: view } ComboBox { id: queryComboBox anchors { left: parent.left top: parent.top margins: 15 } property int bestWidth: implicitWidth width: bestWidth + leftPadding + rightPadding model: ["Choose a SQL where clause", "UseType = 'Government'", "UseType = 'Residential'", "UseType = 'Irrigated Farm'", "TaxRateArea = 10853", "TaxRateArea = 10860", "Roll_LandValue > 1000000", "Roll_LandValue < 1000000"] onCurrentTextChanged: { model.runQuery(queryComboBox.currentText) } }
-
Press Ctrl + R to run the app.
The app loads with the map centered on the Santa Monica Mountains in California with the parcels feature layer displayed. Choose an attribute expression, and parcels in the current extent that meet the selected criteria will display in the specified selection color.
What's next?
Learn how to use additional API features, ArcGIS location services, and ArcGIS tools in these tutorials: