Complex Query (dojo.store)

For stable use of the dojo.store API in map.apps the definition of a store is extended by following aspects:

The dojo.store API was introduced by dojo 1.6. Common Information to the dojo.store API can be found here:

Complex Query Language

One of the main problems for further usage of the API is the leak of a Complex Query Language. The default query definition only supports property equality and "AND" expressions.

A query language parseable by storage implementors to build backend server queries is required. So the language must evaluate in the browser memory and must be completely translateable, for example into sql queries.

As base a json query language designed by mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries is chosen.

Queries in MongoDB 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 } }
          ]
      }
   ]
});

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 AGS 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.

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" and/or "wkt" string, like possible with the 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.

Currently 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

}