Using QueryTask, Query, and FeatureSetE-mail This Topic Printable Version Give Us Feedback

QueryTask, Query, and FeatureSet are used together to query a layer in a map and display the results.

The input into the process is Query. A user provides input to the query. This input might include selecting features on a map, selecting a value from a list, or typing in a value. The input is used to create a query filter. In the next step of the process, the QueryTask is executed based on the query filter. In the final step of the process, the results are returned in a FeatureSet. These results include the geometry of each feature selected for highlighting the features on the map. It also includes the tablular data for display in an InfoWindow or an HTML table.

The following example is a QueryTask where the user types in a population. Based on this input, all cities with a population greater than the value are highlighted on the map. When a user clicks on a city, an InfoWindow displays information about the city. [Show me]

The following discussion assumes you are already familiar with the basic concepts of the JavaScript API and Dojo, and you understand the basic patterns of how the JavaScript API works within an HTML page. For more information, see Adding a map and Adding a task.

Create the init() function

You can use the Init function to initialize the classes you will use in later functions.
  1. Initialize a Map and add a Layer.
  2. Initialize a QueryTask layer. Note that the URL includes the layer ID. In this example, the layer ID is "0".
  3. Initialize the Query. You should specify everything except the actual filter. In this example, a list of output fields is included in outFields. When you specify the output fields, you should limit the fields only to those you expect to use in the query or the results. The fewer fields you include, the faster the response will be. You must use the actual field names rather than the alias names, but you can use the alias names later when you display the results.
  4. Initialize InfoTemplate. If you plan to use an InfoWindow to display the results, this is a good time to construct the InfoTemplate. The syntax ${fieldName} is substituted at runtime with the actual attribute value. The first value is the title. The rest of the values make up the text of the InfoWindow. You can use any valid HTML.
  5. Initialize the Symbol you want to use for displaying the highlighted features on the map.
  function init() {
    //create map and add layer
    map = new esri.Map("mapDiv");
    var layer = new esri.layers.ArcGISDynamicMapServiceLayer("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer");
    map.addLayer(layer);

    //initialize query task
    queryTask = new esri.tasks.QueryTask("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/0");

    //initialize query
    query = new esri.tasks.Query();
    query.returnGeometry = true;
    query.outFields = ["CITY_NAME", "STATE_NAME", "POP1990"];

    //initialize InfoTemplate
    infoTemplate = new esri.InfoTemplate("${CITY_NAME}", "Name : ${CITY_NAME}<br/> State : ${STATE_NAME}<br />Population : ${POP1990}");

    //create symbol for selected features
    symbol = new esri.symbol.SimpleMarkerSymbol();
    symbol.setStyle(esri.symbol.SimpleMarkerSymbol.STYLE_SQUARE);
    symbol.setSize(10);
    symbol.setColor(new dojo.Color([255,255,0,0.5]));

  }
    

executeQueryTask function - the callback function

Create the query filter based on user input and execute the query. User input might include selecting features on a map, selecting a value from a list, or typing in a value. In this example, the user is instructed to enter a population value.

Create the callback function executeQueryTask()

The callback function is the function referenced from the input in the HTML page. In this example, a function named "executeQueryTask" is called after a user types in a population value and clicks the "Get Details" button.

The "population" value is plugged into Query.where. The where attribute is one of three filters you can use with Query:

After you have created the query filter, you execute the query. You do this through the QueryTask.execute() method. The inputs to the method are the Query and a reference to a function named "showResults".
  function executeQueryTask(population) {
    //set query based on what user typed in for population;
    query.where = "POP04 > " + population;

    //execute query
    queryTask.execute(query,showResults);
  }
    

Create a function to show the results

The showResults() function has a FeatureSet as input. The FeatureSet is populated when the query is executed. This function parses the results in the FeatureSet and adds them to the GraphicsLayer. The geometry is used to draw graphic features on the map. The attribute values are added to graphic using the InfoTemplate. When a user clicks on a highlighted feature, an InfoWindow pops up with the results.
  function showResults(featureSet) {
    //remove all graphics on the maps graphics layer
    map.graphics.clear();

    //Performance enhancer - assign featureSet array to a single variable.
    var resultFeatures = featureSet.features;

    //Loop through each feature returned
    for (var i=0, il=resultFeatures.length; i<il; i++) {
      //Get the current feature from the featureSet.
      //Feature is a graphic
      var graphic = resultFeatures[i];
      graphic.setSymbol(symbol);

      //Set the infoTemplate.
      graphic.setInfoTemplate(infoTemplate);

      //Add graphic to the map graphics layer.
      map.graphics.add(graphic);
    }
  }
    

HTML BODY

The BODY section contains what the user sees on the HTML page.

  <body>
    <br/>
    US city population greater than : <input type="text" id="population" value="500000" />
    <input type="button" value="Get Details" onclick="executeQueryTask(dojo.byId('population').value);" />

    <div id="mapDiv" style="width:600px; height:600px; border:1px solid #000;"></div>
    Click on a city once it's highlighted to get an InfoWindow.

  </body>
     

Performance Considerations

You need to be careful that the query you are constructing is reasonable. Your audience will not understand the data as well as you. As a result, users may make queries that are unrealistic or request too much data. There is a direct correlation between performance and the number of features selected.

Queries on cached layers do not have scale dependencies. This means that features for a layer can be queried even if the layer is not displayed on the map for a given scale. Thus, your query should not be accessible for a layer if displaying the results does not make sense to the end user.

You should also consider that users can inadvertently or maliciously request unlimited numbers of features. The maximum number of features returned is the MaxRecordCount set in the map service configuration file. By default, this maximum is set to 500 features. Some common ways a user can request the maximum number of records for a layer are:

You can trap for these types of queries in your application. If you are hosting services that other users may include in their application, you may want to protect your site from multiple large requests by limiting the number of features that can be returned in a query response by setting a reasonable value in MaxRecordCount.