Complex Query (dojo/store)

The dojo/store API is available with Dojo 1.6 and later. General information for the dojo/store API can be found here:

Complex Query Language

One of the main challenges when using the dojo/store API is the lack of a versitile language to query objects. The provided query interface only supports checks for property equality and "AND" expressions. This is especially limiting when building storage implementations, for example for backend servers that provide a richer query interface.

To provide a solution, map.apps defines the Complex Query Language that has the following features:

  • parsable by storage implementors

  • allow translation into other query languages, like SQL

  • provide for efficient evaluation, for example in browsers

The Complex Query Language is inspired by MongoDB’s query language .

Queries using the Complex Query Language are represented as JSON-style objects, for example:

Basic query sample
// simple query: find all items where i.a == 'test' and i.x == 1;
store.query({
    a : "test",
    x : 1
});

// complex query: find all items where i.a starts with 'test' and i.x < 1;
store.query({
 a : {
   $eqw: "test*"
 },
 x : {
   $lt : 1
 }
});

// complex query: find all items where i.a starts with 'test' and (i.x < 1 or i.x > 2);
store.query({
   $and: [
      {
          a: { $eqw: "test*" }
      },{
          $or: [
              { x: { $lt : 1 } },
              { x: { $gt : 2 } }
          ]
      }
   ]
});

Basic Operators

Following operators are specified:

Operator Sample Description

$eq

store.query({
 x : {$eq : 1}
});// the default operatorstore.query({
 x : 1
});

i.x == 1

$gt

store.query({
 x : {$gt : 1}
});

i.x > 1

$gte

store.query({
 x : {$gte : 1}
});

i.x >= 1

$lt

store.query({
 x : {$lt : 1}
});

i.x < 1

You can express ranges with $lt and $gt operators:

 x : {
      $gt : 1,
      $lt : 5
    }
});

$lte

store.query({
 x : {$lte : 1}
});

i.x <= 1

$exists

store.query({
 x : {$exists : true}
});

i.x !== null && i.x !== undefined

Finds items, which have a property named "x".

{$exists: false} finds all items which doesn’t have the property.

$or

store.query({
   $or : [{ x : 1 },{ x : 2 }]
});

i.x == 1 || i.x == 2

$or expects an array of operands!

$and

store.query({
  $and : [{ x : 1 },{ y : 2 }]
});

i.x == 1 && i.y == 2

$and is the default if you don’t specify an operator, so {x: 1,y:2} is the same as the sample.

$and helps to let you match against multiple array values, for example:

var store = new Memory({data: [{ x : [1,2,3,4]}] });var result = store.query({
    $and : [{ x : 1 },{ x : 2 }]
});

→ result is found and the array i.x, has the values 1 and 2.

$in

store.query({
   x : {$in : [1,2,3]}

});

i.x == 1 || i.x == 2 || i.x == 3

The $in operator is analogous to the SQL IN modifier, allowing you to specify an array of possible matches.

$not

store.query({
   x : {$not : {$gt : 2 }}

});

!(i.x > 2)

Negates the result of another operator.

$eqw

store.query({
   x : {$eqw: "B?roheng*"}

});

i.x == /B.roheng.*/

A string value operator, for explicite wildcard support. Wildcards are:

'?' = single char

'*' = chars

$suggest

store.query({
  name : {$suggest : "London"}
});

Make a suggestion/guess search. Looking for i.name == "London" or any semantic equal item.

The exact meaning of "suggest" is implementation specific and requires semantic knowlege of the items.

A simple implementation maps $suggest to a $eqw search.

$elemMatch

store.query(
    "array": {
        "$elemMatch": [{
            name: "a"
        }]
    }
);

Selects results if element in the array field matches all the specified $elemMatch conditions.

The sample matches:

{ array: [ { name:"a" }, { name:b }] }

Spatial Operators

Spatial Operators are also defined.

Operator Sample Description

$intersects

store.query({
   geometry : { $intersects: g }
});

Query Geometry Intersects Target Geometry.

Returns a feature if any spatial relationship is found. Applies to all shape type combinations

$contains

store.query({
   geometry : { $contains: g }
});

Query Geometry Contains Target Geometry.

Returns a feature if its shape is completely contained by the search geometry g. Valid for all shape type combinations.

(Find all geometries which are completely contained by the search geometry g)

$crosses

store.query({
   geometry : { $crosses: g }
});

Query Geometry Crosses Target Geometry.

Returns a feature if the intersection of the interiors of the two shapes is not empty and has a lower dimension than the maximum dimension of the two shapes. Two lines that share an endpoint in common do not cross. Valid for Line/Line, Line/Area, Multi-point/Area, and Multi-point/Line shape type combinations.

$envelope-intersects

store.query({
   geometry : {
      $envelope-intersects: g
   }
});

Envelope of Query Geometry Intersects Envelope of Target Geometry.

Returns a feature if the envelope of the two shapes intersects.

$envelopeintersects

store.query({
   geometry : {
      $envelopeintersects: g
   }
});

Envelope of Query Geometry Intersects Envelope of Target Geometry.

Returns a feature if the envelope of the two shapes intersects.

Deprecated
Use $envelope-intersects instead.

$bbox

store.query({
   geometry : { $bbox: g }
});

Same as $envelopeintersects

$overlaps

store.query({
   geometry : {
      $overlaps: g
   }
});

Query Geometry Overlaps Target Geometry.

Returns a feature if the intersection of the two shapes results in an object of the same dimension, but different from both of the shapes. Applies to Area/Area, Line/Line, and Multi-point/Multi-point shape type combinations.

$touches

store.query({
   geometry : { $touches: g }
});

Query Geometry Touches Target Geometry.

Returns a feature if the two shapes share a common boundary. However, the intersection of the interiors of the two shapes must be empty. In the Point/Line case, the point can touch an endpoint only of the line. Applies to all combinations except Point/Point.

$within

store.query({
   geometry : { $within: g }
});

Query Geometry is Within Target Geometry.

Returns a feature if the search geometry g is completely within the feature. Points don’t have a within function. All other shape type combinations are possible.

(Find all geometries which completely contain the search geometry g)

Do not use multiple geometry operators in a single query, because the ArcGIS Server supports only one server-side spatial query operation.

Query Options

An options object is defined as second parameter to the "query" operation of a dojo/store.

Option Description
{ count : 10 }

Specifies the maximum number of features to return.

-1 = return all (honors server-side limit)

0 = return no features, only total matching feature count is requested

default: -1

{ start : 9 }

Server shall start returning the element with index 9 (0 is first) of the result set of the query

start and count are used to implement paging

{sort : [{attribute:"title", descending: true}]}

Defines the ordering of the result set.

{ ignoreCase : true }

Modifies any string operator to be case insensitive.

{ fields: {
   title : 1
}}
{ fields: {
   geometry : 0
}}

Defines which fields are provided in the result set.

1 = include

0 = exclude

All fields are requested if fields is not specified. If sort options are added, the sort attributes are added to the fields array internally and therefor in that case not all fields are requested.

To implement the "exclude" pattern, a store implementation must know about the available fields. Set geometry to 0 in that case, to request fields only.

{ locale : {language : "de", country : "DE"} }

The locale of the query. This is of relavance if the server is able to match "Köln" to "Cologne".

{ geometry : {      sr : { wkid: 4326 }}}

The spatial reference system in which the requested server shall return the geometry field.

You can specify wkid or wkt string, like possible with esri.SpatialReference.

{ geometry : {      maxAllowableOffset : 10000}}

Generalisation option of the returned feature geometries.

Result Item Structure

A store might return any item. geometry must be used as common attribute name for geometries.

Following property names must be used:

Name Description

geometry

The geometry of a feature. Must be a esri.geometry.Geometry.

extent

(optinal) Additional extent information, for example for point geometries. Must be a esri.geometry.Extent.

getMetadata Operation

A store can provide a getMetadata operation like defined in the dojo/store/api/Store interface.

The getMetadata operation is not further specified in the API definition.

The function is used the following way:

getMetadata
// is the item required, or is store metadata defined without the scope of an item?
var item = store.get("test");
var metadata = store.getMetadata(item);
dojo.when(metadata,function(metadata) {
    var fields = metadata.fields;
    // ... do something with the fields
});

//metadata like (maybe more definitions are needed, for example for fields to add auto validation or edit form creation)?
var m = {
     title : "My Store",
     description : "",
     displayField : "title"
     fields : [{
          name : "title",
          title: "Title",
      type : "string"
     },
     {
         name : "geometry",
         title: "SHAPE",
         type : "geometry"
    },
    {
     name : "type",
     title: "Feature Type",
     type : "string"
   }]
   supportsSorting : true // optional flag, if set to 'false', sorting of columns in Dgrid-View is disabled
   supportsGeometry: true // flag to indicate if store supports spatial operations

}