Find features in a feature table which match an SQL query.
Use case
Query expressions can be used in ArcGIS to select a subset of features from a feature table. This is most useful in large or complicated data sets. A possible use case might be on a feature table marking the location of street furniture through a city. A user may wish to query by a TYPE column to return "benches". In this sample, we query a U.S. state by STATE_NAME from a feature table containing all U.S. states.
How to use the sample
Input the name of a U.S. state into the text field. When you click "search", a query is performed and the matching features are highlighted or an error is returned.
How it works
- Create a
ServiceFeatureTableusing the URL of a feature service. - Create a
QueryParameterswith a where clause specified usingsetWhereClause(). - Perform the query using
queryFeaturesAsync(query)on the service feature table. - When complete, the query will return a
FeatureQueryResultwhich can be iterated over to get the matching features.
About the data
This sample uses U.S. State polygon features from the USA 2016 Daytime Population feature service.
Relevant API
- FeatureLayer
- FeatureQueryResult
- QueryParameters
- ServiceFeatureTable
Tags
Search and Query
Sample Code
// [WriteFile Name=FeatureLayerQuery, Category=Features]
// [Legal]
// Copyright 2016 Esri.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// [Legal]
#ifdef PCH_BUILD
#include "pch.hpp"
#endif // PCH_BUILD
// sample headers
#include "FeatureLayerQuery.h"
// ArcGIS Maps SDK headers
#include "Basemap.h"
#include "Feature.h"
#include "FeatureIterator.h"
#include "FeatureLayer.h"
#include "FeatureQueryResult.h"
#include "LayerListModel.h"
#include "Map.h"
#include "MapQuickView.h"
#include "MapTypes.h"
#include "MapViewTypes.h"
#include "Point.h"
#include "QueryParameters.h"
#include "ServiceFeatureTable.h"
#include "SimpleFillSymbol.h"
#include "SimpleLineSymbol.h"
#include "SimpleRenderer.h"
#include "SpatialReference.h"
#include "SymbolTypes.h"
#include "Viewpoint.h"
// Qt headers
#include <QColor>
#include <QFuture>
#include <QList>
#include <QUrl>
#include <QUuid>
// STL headers
#include <memory>
using namespace Esri::ArcGISRuntime;
FeatureLayerQuery::FeatureLayerQuery(QQuickItem* parent) :
QQuickItem(parent)
{
}
FeatureLayerQuery::~FeatureLayerQuery() = default;
void FeatureLayerQuery::init()
{
qmlRegisterType<MapQuickView>("Esri.Samples", 1, 0, "MapView");
qmlRegisterType<FeatureLayerQuery>("Esri.Samples", 1, 0, "FeatureLayerQuerySample");
}
void FeatureLayerQuery::componentComplete()
{
QQuickItem::componentComplete();
// find QML MapView component
m_mapView = findChild<MapQuickView*>("mapView");
m_mapView->setWrapAroundMode(WrapAroundMode::Disabled);
// Create a map using the topographic basemap
m_map = new Map(BasemapStyle::ArcGISTopographic, this);
m_map->setInitialViewpoint(Viewpoint(Point(-11e6, 5e6, SpatialReference(102100)), 9e7));
// Set map to map view
m_mapView->setMap(m_map);
// create the feature table
m_featureTable = new ServiceFeatureTable(QUrl("https://services.arcgis.com/jIL9msH9OI208GCb/arcgis/rest/services/USA_Daytime_Population_2016/FeatureServer/0"), this);
// create the feature layer using the feature table
m_featureLayer = new FeatureLayer(m_featureTable, this);
// line symbol for the outline
SimpleLineSymbol* outline = new SimpleLineSymbol(SimpleLineSymbolStyle::Solid, QColor("black"), 2.0f, this);
// fill symbol
SimpleFillSymbol* sfs = new SimpleFillSymbol(SimpleFillSymbolStyle::Solid, QColor(255, 255, 0, 153), outline, this);
// create the renderer using the symbology created above
SimpleRenderer* renderer = new SimpleRenderer(sfs, this);
// set the renderer for the feature layer
m_featureLayer->setRenderer(renderer);
m_featureLayer->setMaxScale(10000);
// add the feature layer to the map
m_map->operationalLayers()->append(m_featureLayer);
connect(m_featureTable, &ServiceFeatureTable::loadStatusChanged, this, [this](LoadStatus loadStatus)
{
loadStatus == LoadStatus::Loaded ? m_initialized = true : m_initialized = false;
emit layerInitializedChanged();
});
}
bool FeatureLayerQuery::layerInitialized() const
{
return m_initialized;
}
void FeatureLayerQuery::runQuery(const QString& stateName)
{
// create a query parameter object and set the where clause
QueryParameters queryParams;
queryParams.setWhereClause(QString("STATE_NAME LIKE '" + formatStateNameForQuery(stateName) + "%'"));
m_featureTable->queryFeaturesAsync(queryParams).then(this, [this](FeatureQueryResult* rawQueryResult)
{
auto queryResult = std::unique_ptr<FeatureQueryResult>(rawQueryResult);
if (queryResult && !queryResult->iterator().hasNext())
{
m_queryResultsCount = 0;
emit queryResultsCountChanged();
return;
}
// 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 the feature
m_featureLayer->selectFeatures(features);
// zoom to the first feature
m_mapView->setViewpointGeometryAsync(features.at(0)->geometry(), 30);
// set the count for QML property
m_queryResultsCount = static_cast<int>(features.count());
emit queryResultsCountChanged();
});
}
QString FeatureLayerQuery::formatStateNameForQuery(const QString& stateName) const
{
// format state names as expected by the service, for instance "Rhode Island"
if (stateName.isEmpty())
return QString();
const QStringList words = stateName.split(" ", Qt::SkipEmptyParts);
QStringList formattedWords;
for (const QString& word : words)
{
QString formattedWord = word.toLower();
formattedWord[0] = formattedWord[0].toUpper();
formattedWords.append(formattedWord);
}
return QString(formattedWords.join(" "));
}
int FeatureLayerQuery::queryResultsCount() const
{
return m_queryResultsCount;
}