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. A query is performed and the matching features are highlighted or an error is returned.
How it works
- Create an
AGSServiceFeatureTable
using the URL of a feature service. - Create
AGSQueryParameters
with awhereClause
specified. - Perform the query using
AGSFeatureTable.queryFeatures(with:completion:)
on the service feature table. - When complete, the query will return an
AGSFeatureQueryResult
which can be iterated over to get the matching features.
Relevant API
- AGSFeatureLayer
- AGSFeatureQueryResult
- AGSQueryParameters
- AGSServiceFeatureTable
About the data
This sample uses U.S. State polygon features from the USA 2016 Daytime Population feature service.
Tags
query, search
Sample Code
// 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.
import UIKit
import ArcGIS
class FLQueryViewController: UIViewController, UISearchBarDelegate {
@IBOutlet private weak var mapView: AGSMapView!
private var featureTable: AGSServiceFeatureTable?
private var featureLayer: AGSFeatureLayer?
private var selectedFeatures = [AGSFeature]()
override func viewDidLoad() {
super.viewDidLoad()
// add the source code button item to the right of navigation bar
(navigationItem.rightBarButtonItem as! SourceCodeBarButtonItem).filenames = ["FLQueryViewController"]
// initialize map with topographic basemap
let map = AGSMap(basemapStyle: .arcGISTopographic)
// assign map to the map view
mapView.map = map
/// The url of a map service layer containing sample census data of United States counties.
let statesFeatureTableURL = URL(string: "https://services.arcgis.com/jIL9msH9OI208GCb/arcgis/rest/services/USA_Daytime_Population_2016/FeatureServer/0")!
// create feature table using a url
let featureTable = AGSServiceFeatureTable(url: statesFeatureTableURL)
self.featureTable = featureTable
// create feature layer using this feature table
let featureLayer = AGSFeatureLayer(featureTable: featureTable)
self.featureLayer = featureLayer
// show the layer at all scales
featureLayer.minScale = 0
featureLayer.maxScale = 0
// set a new renderer
let lineSymbol = AGSSimpleLineSymbol(style: .solid, color: .black, width: 1)
let fillSymbol = AGSSimpleFillSymbol(style: .solid, color: UIColor.yellow.withAlphaComponent(0.5), outline: lineSymbol)
featureLayer.renderer = AGSSimpleRenderer(symbol: fillSymbol)
// add feature layer to the map
map.operationalLayers.add(featureLayer)
// center the layer
mapView.setViewpointCenter(AGSPoint(x: -11e6, y: 5e6, spatialReference: .webMercator()), scale: 9e7)
}
func selectFeaturesForSearchTerm(_ searchTerm: String) {
guard let featureLayer = featureLayer,
let featureTable = featureTable else {
return
}
// deselect all selected features
if !selectedFeatures.isEmpty {
featureLayer.unselectFeatures(selectedFeatures)
selectedFeatures.removeAll()
}
let queryParams = AGSQueryParameters()
queryParams.whereClause = "upper(STATE_NAME) LIKE '%\(searchTerm.uppercased())%'"
featureTable.queryFeatures(with: queryParams) { [weak self] (result: AGSFeatureQueryResult?, error: Error?) in
guard let self = self else {
return
}
if let error = error {
// display the error as an alert
self.presentAlert(error: error)
} else if let features = result?.featureEnumerator().allObjects {
if !features.isEmpty {
// display the selection
featureLayer.select(features)
// zoom to the selected feature
self.mapView.setViewpointGeometry(features.first!.geometry!, padding: 25)
} else {
if let fullExtent = featureLayer.fullExtent {
// no matches, zoom to show everything in the layer
self.mapView.setViewpointGeometry(fullExtent, padding: 50)
}
}
// update selected features array
self.selectedFeatures = features
}
}
}
// MARK: - Search bar delegate
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
if let text = searchBar.text {
selectFeaturesForSearchTerm(text)
}
searchBar.resignFirstResponder()
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.resignFirstResponder()
}
}