Map Service QueryData method

Queries and returns a record set of features or rows that meet the query filter selection criteria for the specified layer or table description.


QueryData(string MapName, MapTableDescription MapTableDescription, QueryFilter QueryFilter, QueryResultOptions QueryResultOptions)





The name of the map (data frame) that contains the layer associated with the MapTableDescription parameter.


Used to set the definition expression to a layer or a standalone table.


An attribute or spatial query that defines the selection criteria for the layer or standalone table associated with the MapTableDescription parameter.


Used to define the output format of a query result and a GeoTransformation to apply to the results.


Return Value


This method returns the records of map features that match the parameters of a given query filter in a QueryResult object. The returned object’s format is defined by Format property of the QueryResultOptions parameter, a QueryResultOptions object. This format can be a recordset, KML, JSON or AMF for a layer. Please note that the result format for a standalone table is restricted to recordset only.


For KML (Keyhole Markup Language), JSON (JavaScript Object Notation) or AMF (Action Message Format), result can be passed back as a URL (when QueryResultOptions.Format is "esriQueryResultKMLAsURL") or as a MIME object (when QueryResultOptions.Format is "esriQueryResultKMLAsMime"). KML is returned in compressed KMZ format.


When "esriQueryResultRecordSetAsObject" is selected as QueryResultOptions.Format, the function returns a RecordSet object.




The required input parameters include: MapName, MapTableDescription, and QueryFilter. The QueryFilter can be an attribute query (SQL expression), a spatial query, a time query, a combination of all or null. LayerDescription has SourceID property that can be used to query against a GP result.


MapTableDescription is an identifier class implemented by LayerDescription and StandaloneTableDescription classes. LayerDescription for a layer can be obtained from MapServerInfo.DefaultMapDescription while StandaloneTableDescription can be obtained using MapServerInfo.StandaloneTableDescriptions property.




QueryFilter provides the ability to query based on attribute filter (SQL expression) a spatial filter, or a combination of both. Attribute filters take any valid 'non-GIS data specific' SQL statement. For example, CNTRY_CODE = 'BD' or POPULATION = 12345. Syntax for querying date fields depend on the underlying data. If you are working with Shapefile or File GeoDatabase data the syntax is <FieldName> = date 'YYYY-MM-DD' for Access-based Personal GeoDatabase the syntax is #YYYY-MM-DD#. For SDE database, check with the specific database’s help.


It can be set to null or Nothing to retrieve all data (which is also limited by MaxRecordCount).


If geometry is not desired in the output RecordSet, QueryFilter’s SubFields must be defined without "Shape" field. When SubFields is empty or includes "Shape", the RecordSet will include the fields "shape_length" and "shape_area". If the desired spatial reference of the output geometry is different than the original one, OutputSpatialReference should be used. Otherwise geometry is returned in the same spatial reference system as the DefaultMapDescription by default. When SubFields is not defined or = "*", it returns all visible fields. Invisible or invalid field names or field aliases must not be included in SubFields string or it will return an error.  Please note ObjectID field is always returned regardless of whether it is in the SubFields or not. The only exception is when DISTINCT is used.


When only the unique value from a field is desired, you need to set PrefixClause to "DISTINCT". In case when you want the result sorted by field(s), set ORDER BY <field1, field2,...> to PostfixClause. Please note these options will only be honored when the source database supports that such as ArcSDE GeoDatabase, File GeoDatabase and Personal GeoDatabase. ORDER BY is not supported on a field from a joined table.


Spatial Filters


Geometry set in SpatialFilter should meet the following criteria:





When a layer is time aware (use MapLayerInfo.SupportsTime property), a query can be made to retrieve a set of features that are available at a specific time or for a period of time. In order to perform a time query, a TimeQueryFilter object needs to created and passed in to this function. An attribute or spatial query can be combined with time.


Values in StartTimeFieldName or EndTimeFieldName are returned in the Layer's TimeReference. If the desired time reference is different than the layer's one, OutputTimeReference should be explicitly set.


Definition Expressions


A definition expression can be set on a layer or a standalone table in order to limit layer features or rows available for display or query. This expression can be also be set in the source map document as a definition query. LayerDescription.DefinitionExpression or StandaloneTableDescription.DefinitionExpression  will override any definition query set in the source map. This method honors DefinitionExpression.


Let's look at some examples. You have a layer in your map that represents sales regions. The layer includes fields REGIONS, SALES and MANAGER.


Example #1: In the source map the layer has a definition query, "REGION = 'North'". No DefinitionExpression is specified in LayerDescription. Your QueryFilter where clause is "MANAGER = 'Bob'". The result will be all sale region features that fall within the North region and are managed by Bob.


Example #2: In the source map the layer has a definition query, "REGION = 'North'". You apply a DefinitionExpression in LayerDescription as "SALES > 1000". Your QueryFilter.WhereClause  is "MANAGER = 'Bob'". The result will be all sale region features with sales over 1000 and are managed by Bob. This method honors the DefinitionExpression set in LayerDescription. The DefinitionExpression overrides the definition query set in the source map. If you wish to include the layer's original definition query, "REGION = 'North'" in your final query, you must include this in your QueryFilter, ""MANAGER = 'Bob' AND "REGION = 'North'".


Example #3: In the source map the layer has no definition query. You apply a DefinitionExpression in LayerDescription as "SALES > 1000". Your QueryFilter where clause is "MANAGER = 'Bob'". The result will be all sale region features with sales over 1000 and are managed by Bob. QueryData honors the DefinitionExpression set in LayerDescription.




Setting QueryResultOptions has no effect on KML output.




When "esriQueryResultRecordSetAsObject" is selected as Format of QueryResultOptions, it returns a RecordSet object. Use QueryResult.Object property to access that. The returned object needs to be QI to a RecordSet.


Result Geometry:


By default, geometry is returned in the same spatial reference as the MapServerInfo.DefaultMapDescription. The spatial reference of this method's results can be set to something different than the MapServerInfo.DefaultMapDescription by using QueryFilter.OutputSpatialReference.  Both OutputSpatialReference and SpatialReferenceFieldName (of a field of geometry type) properties are required and must be set.


In some instances the result may require a GeoTransformation. For example, a given map service may be using a spatial reference system based on GCS_WGS_1984. A client wants to display QueryData results based on this map service in a different spatial reference, GCS_European_1950. The results will use the spatial reference of the MapServerInfo.DefaultMapDescription, GCS_WGS_1984, and display these results incorrectly in GCS_European_1950. Features may not "line up" correctly. In order to correctly display these results a GeoTransformation is needed. Applying the correct one ensures the spatial correctness of the result. QueryResultOptions.GeoTransformation can be used to specify this if one is needed.


Another instance where a GeoTransformation may be needed to be specified in the QueryResultOptions is if the queried layer is projected on the fly within the map service. That is, the coordinate system of the layer's source is different than the MapServerInfo.DefaultMapDescription coordinate system, and no appropriate transformation has been set in the map document before serving. In this case, you can access the coordinate system of a layer source by first getting the layer's MapLayerInfo, then get Fields from this object, get the "Shape" field from Fields, get GeometryDef from the Field, and finally, get the SpatialReference from GeometryDef.


A GeoTransformation is not needed if the projected coordinate systems share the same underlying geographic coordinate system. For best results it is optimal for data (layers within the map service), map service and MapServer output to use the same coordinate system.


In some cases, may be for performance reasons, you may want limit or adjust the geometry being returned in the record set result. Use LayerResultOptions to manage this. If IncludeGeometry is set to False, geometry is not included in the recordset. This should increase performance in cases where feature geometry is large. You can also choose to densify or generalize the returned geometry by using GeometryResultOptions. Densification is used to better support clients that do not support Arcs (e.g. Bezier, Circular, etc.). Generalization reduces the amount of geography being sent across the network and should lead to better performance.


Field visibility and field aliases:


This method honors field visibility set in the source map document. Field aliases, set in the source map document, are honored. However, the RecordSet does NOT honor any field formatting set in the source map.




In order to control the amount of information MapServer needs to process for a query, a maximum number of records can be set. This value is contained in the MaxRecordCount property accessed by using  GetServiceConfigurationInfo. The default value for this property is 500. If 600 features match a given query only the first 500 results will be returned. You will be unable to access the remaining 100 records. To be able to access these records the MaxRecordCount would need to be increased to 600.


There are two key differences between Find and this method. The first is that Find can work on multiple layers while the query methods work with a single layer. The second is that Find only works with a search string. The query methods use a QueryFilter as a parameter. This allows the query to be based on either an attribute filter (SQL expression) or a spatial filter.




In case where both QueryFilter.SubFields and LayerResultOption.IncludeGeometry is set, SubFields takes precedence over IncludeGeometry. For example, when SubFields = "Shape, FName, LName, Address" and IncludeGeometry = False, the output recordset will contain geometry as contained within the Shape field.