Session: Querying: How to Query a Spatial Index


  • Spatial indexes can be queried using the Spatial method which contains a full spectrum of spatial methods. The following article will cover the methods Spatial(), OrderByDistance(), and OrderByDistanceDescending.

  • In this page:


Spatial

IRavenQueryable<T> Spatial<T>(
    Expression<Func<T, object>> path,
    Func<SpatialCriteriaFactory, SpatialCriteria> clause);

IRavenQueryable<T> Spatial<T>(
    string fieldName,
    Func<SpatialCriteriaFactory, SpatialCriteria> clause);

IRavenQueryable<T> Spatial<T>(
    Func<DynamicSpatialFieldFactory<T>, DynamicSpatialField> field,
    Func<SpatialCriteriaFactory, SpatialCriteria> clause);

IRavenQueryable<T> Spatial<T>(
    DynamicSpatialField field,
    Func<SpatialCriteriaFactory, SpatialCriteria> clause);
Parameters
path Expression<Func<T, object>> Path to spatial field in an index
fieldName string Path to spatial field in an index
field Func<DynamicSpatialFieldFactory<T>, DynamicSpatialField> or DynamicSpatialField Factory or field that points to a dynamic field (used with auto-indexes). Either PointField or WktField
clause Func<SpatialCriteriaFactory, SpatialCriteria> Spatial criteria that will be executed on a given spatial field from the path parameter.

DynamicSpatialFieldFactory

PointField Point(
    Expression<Func<T, object>> latitudePath,
    Expression<Func<T, object>> longitudePath);

WktField Wkt(Expression<Func<T, object>> wktPath);
Parameters
latitudePath or longitudePath or wktPath Expression<Func<T, object>> Path to the field in a document containing either longitude, latitude or WKT

SpatialCriteriaFactory

SpatialCriteria RelatesToShape(
    string shapeWkt,
    SpatialRelation relation,
    double distErrorPercent = Constants.Documents.Indexing.Spatial.DefaultDistanceErrorPct);

SpatialCriteria RelatesToShape(
    string shapeWkt,
    SpatialRelation relation,
    SpatialUnits units,
    double distErrorPercent = Constants.Documents.Indexing.Spatial.DefaultDistanceErrorPct);

SpatialCriteria Intersects(
    string shapeWkt,
    double distErrorPercent = Constants.Documents.Indexing.Spatial.DefaultDistanceErrorPct);

SpatialCriteria Intersects(
    string shapeWkt,
    SpatialUnits units,
    double distErrorPercent = Constants.Documents.Indexing.Spatial.DefaultDistanceErrorPct);

SpatialCriteria Contains(
    string shapeWkt,
    double distErrorPercent = Constants.Documents.Indexing.Spatial.DefaultDistanceErrorPct);

SpatialCriteria Contains(
    string shapeWkt,
    SpatialUnits units,
    double distErrorPercent = Constants.Documents.Indexing.Spatial.DefaultDistanceErrorPct);

SpatialCriteria Disjoint(
    string shapeWkt,
    double distErrorPercent = Constants.Documents.Indexing.Spatial.DefaultDistanceErrorPct);

SpatialCriteria Disjoint(
    string shapeWkt,
    SpatialUnits units,
    double distErrorPercent = Constants.Documents.Indexing.Spatial.DefaultDistanceErrorPct);

SpatialCriteria Within(
    string shapeWkt,
    double distErrorPercent = Constants.Documents.Indexing.Spatial.DefaultDistanceErrorPct);

SpatialCriteria Within(
    string shapeWkt,
    SpatialUnits units,
    double distErrorPercent = Constants.Documents.Indexing.Spatial.DefaultDistanceErrorPct);

SpatialCriteria WithinRadius(
    double radius,
    double latitude,
    double longitude,
    SpatialUnits? radiusUnits = null,
    double distErrorPercent = Constants.Documents.Indexing.Spatial.DefaultDistanceErrorPct);
Parameter Type Description
shapeWkt string WKT-based shape to be used in operation
relation SpatialRelation Shape relation. Can be Within, Contains, Disjoint, Intersects
distErrorPercent double Maximum distance error tolerance in percents. Default: 0.025
radius or latitude or longitude double Used to define a radius circle
radiusUnits or units SpatialUnits Determines if circle or shape should be calculated in Kilometers or Miles

Polygons

When using spatial.wkt() to define a polygon, the vertices (points that form the corners of the polygon) must be listed in a counter-clockwise order:

NoSQL DB - Query a Spatial Index

Example I

// return all matching entities
// within 10 kilometers radius
// from 32.1234 latitude and 23.4321 longitude coordinates
List<House> results = session
    .Query<House>()
    .Spatial(
        factory => factory.Point(x => x.Latitude, x => x.Longitude),
        criteria => criteria.WithinRadius(10, 32.1234, 23.4321))
    .ToList();
// return all matching entities
// within 10 kilometers radius
// from 32.1234 latitude and 23.4321 longitude coordinates
List<House> results = await asyncSession
    .Query<House>()
    .Spatial(
        factory => factory.Point(x => x.Latitude, x => x.Longitude),
        criteria => criteria.WithinRadius(10, 32.1234, 23.4321))
    .ToListAsync();
from Houses
where spatial.within(spatial.point(Latitude, Longitude), spatial.circle(10, 32.1234, 23.4321))

Example II

// return all matching entities
// within 10 miles radius
// from 32.1234 latitude and 23.4321 longitude coordinates
// this equals to WithinRadius(10, 32.1234, 23.4321)
List<House> results = session
    .Query<House>()
    .Spatial(
        factory => factory.Point(x => x.Latitude, x => x.Longitude),
        criteria => criteria.RelatesToShape(
            "Circle(32.1234 23.4321 d=10.0000)",
            SpatialRelation.Within,
            SpatialUnits.Miles))
    .ToList();
// return all matching entities
// within 10 miles radius
// from 32.1234 latitude and 23.4321 longitude coordinates
// this equals to WithinRadius(10, 32.1234, 23.4321)
List<House> results = await asyncSession
    .Query<House>()
    .Spatial(
        factory => factory.Point(x => x.Latitude, x => x.Longitude),
        criteria => criteria.RelatesToShape(
            "Circle(32.1234 23.4321 d=10.0000)",
            SpatialRelation.Within,
            SpatialUnits.Miles))
    .ToListAsync();
from Houses
where spatial.within(spatial.point(Latitude, Longitude), spatial.wkt('Circle(32.1234 23.4321 d=10.0000)', 'Miles'))

OrderByDistance

To sort by distance from given point use the OrderByDistance method. The closest results will come first.

// From point
IOrderedQueryable<T> OrderByDistance<T>(
    Func<DynamicSpatialFieldFactory<T>, DynamicSpatialField> field,
    double latitude,
    double longitude);

IOrderedQueryable<T> OrderByDistance<T>(
    DynamicSpatialField field,
    double latitude,
    double longitude);

IOrderedQueryable<T> OrderByDistance<T>(
    Expression<Func<T, object>> path,
    double latitude,
    double longitude);

IOrderedQueryable<T> OrderByDistance<T>(
    string fieldName,
    double latitude,
    double longitude);

// From center of WKT shape
IOrderedQueryable<T> OrderByDistance<T>(
    Func<DynamicSpatialFieldFactory<T>, DynamicSpatialField> field,
    string shapeWkt);

IOrderedQueryable<T> OrderByDistance<T>(
    DynamicSpatialField field,
    string shapeWkt);

IOrderedQueryable<T> OrderByDistance<T>(
    Expression<Func<T, object>> path,
    string shapeWkt);

IOrderedQueryable<T> OrderByDistance<T>(
    string fieldName,
    string shapeWkt);

// Rounding
IOrderedQueryable<T> OrderByDistance<T>(
    Expression<Func<T, object>> path,
    double latitude,
    double longitude,
    double roundFactor);

IOrderedQueryable<T> OrderByDistance<T>(
    string fieldName,
    double latitude,
    double longitude,
    double roundFactor);

IOrderedQueryable<T> OrderByDistance<T>(
    Expression<Func<T, object>> path,
    string shapeWkt,
    double roundFactor);

IOrderedQueryable<T> OrderByDistance<T>(
    string fieldName,
    string shapeWkt,
    double roundFactor);
Parameter Type Description
path Expression<Func<T, object>> Path to spatial field in index
fieldName string Path to spatial field in index
field Func<DynamicSpatialFieldFactory<T>, DynamicSpatialField> or DynamicSpatialField Factory or field that points to a dynamic field (used with auto-indexes). Either PointField or WktField
shapeWkt string WKT-based shape to be used as a point from which distance will be measured. If the shape is not a single point, then the center of the shape will be used as a reference.
latitude or longitude double Used to define a point from which distance will be measured
roundFactor double A distance interval in kilometers. The distance from the point is rounded up to the nearest interval. The results within the same interval are then sorted by another order. This other order is the next chained ordering, or if no other order was specified, then by ascending order of document Id. See example below.

Example I

// return all matching entities
// within 10 kilometers radius
// from 32.1234 latitude and 23.4321 longitude coordinates
// sort results by distance from 32.1234 latitude and 23.4321 longitude point
List<House> results = session
    .Query<House>()
    .Spatial(
        factory => factory.Point(x => x.Latitude, x => x.Longitude),
        criteria => criteria.WithinRadius(10, 32.1234, 23.4321))
    .OrderByDistance(
        factory => factory.Point(x => x.Latitude, x => x.Longitude), 32.1234, 23.4321)
    .ToList();
// return all matching entities
// within 10 kilometers radius
// from 32.1234 latitude and 23.4321 longitude coordinates
// sort results by distance from 32.1234 latitude and 23.4321 longitude point
List<House> results = await asyncSession
    .Query<House>()
    .OrderByDistance(
        factory => factory.Point(x => x.Latitude, x => x.Longitude), 32.1234, 23.4321)
    .ToListAsync();
from Houses
where spatial.within(spatial.point(Latitude, Longitude), spatial.circle(10, 32.1234, 23.4321))
order by spatial.distance(spatial.point(Latitude, Longitude), spatial.point(32.1234, 23.4321))

Example II

This example demonstrates rounding. The query sorts the results by distance from the specified point, but rounds the distance up to the nearest 100 km interval. All results within the same interval are sorted alphabetically by the field Name.

// Return all entities and sort results by distance.
// Round the distance up to the nearest 100 km.
// Then sort alphabetically by the entity Name.
List<House> results = session
    .Query<House>()
    .OrderByDistance(
        factory => factory.Point(
            x => x.Latitude,
            x => x.Longitude)
        .RoundTo(100),
        32.1234,
        23.4321)
    .ThenBy(x => x.Name)
    .ToList();
// Return all entities and sort results by distance.
// Round the distance up to the nearest 100 km.
// Then sort alphabetically by the entity Name.
List<House> results = await asyncSession
    .Query<House>()
    .OrderByDistance(
        factory => factory.Point(
            x => x.Latitude,
            x => x.Longitude)
        .RoundTo(100),
        32.1234,
        23.4321)
    .ThenBy(x => x.Name)
    .ToListAsync();
from Houses as h
order by spatial.distance(
    spatial.point(h.Latitude, h.Longitude),
    spatial.point(32.1234, 23.4321),
    100), h.Name

OrderByDistanceDescending

To sort by distance from given point use the OrderByDistanceDescending method. The farthest results will come first.

// From point
IOrderedQueryable<T> OrderByDistanceDescending<T>(
    Func<DynamicSpatialFieldFactory<T>, DynamicSpatialField> field,
    double latitude,
    double longitude);

IOrderedQueryable<T> OrderByDistanceDescending<T>(
    DynamicSpatialField field,
    double latitude,
    double longitude);

IOrderedQueryable<T> OrderByDistanceDescending<T>(
    Expression<Func<T, object>> path,
    double latitude,
    double longitude);

IOrderedQueryable<T> OrderByDistanceDescending<T>(
    string fieldName,
    double latitude,
    double longitude);

// From center of WKT shape
IOrderedQueryable<T> OrderByDistanceDescending<T>(
    Func<DynamicSpatialFieldFactory<T>, DynamicSpatialField> field,
    string shapeWkt);

IOrderedQueryable<T> OrderByDistanceDescending<T>(
    DynamicSpatialField field,
    string shapeWkt);

IOrderedQueryable<T> OrderByDistanceDescending<T>(
    Expression<Func<T, object>> path,
    string shapeWkt);

IOrderedQueryable<T> OrderByDistanceDescending<T>(
    string fieldName,
    string shapeWkt);

// Rounding
IOrderedQueryable<T> OrderByDistanceDescending<T>(
    Expression<Func<T, object>> path,
    double latitude,
    double longitude,
    double roundFactor);

IOrderedQueryable<T> OrderByDistanceDescending<T>(
    string fieldName,
    double latitude,
    double longitude,
    double roundFactor);

IOrderedQueryable<T> OrderByDistanceDescending<T>(
    Expression<Func<T, object>> path,
    string shapeWkt,
    double roundFactor);

IOrderedQueryable<T> OrderByDistanceDescending<T>(
    string fieldName,
    string shapeWkt,
    double roundFactor);
Parameter Type Description
path Expression<Func<T, object>> Path to spatial field in an index
fieldName string Path to spatial field in an index
field Func<DynamicSpatialFieldFactory<T>, DynamicSpatialField> or DynamicSpatialField Factory or field that points to a dynamic field (used with auto-indexes). Either PointField or WktField
shapeWkt string WKT-based shape to be used as a point from which distance will be measured. If the shape is not a single point, then the center of the shape will be used as a reference.
latitude or longitude double Used to define a point from which distance will be measured
roundFactor double A distance interval in kilometers. The measured distance is rounded up to the nearest interval. The results within the same distance interval are then sorted by another order. This other order is the next chained ordering, or if no other order was specified, then by ascending order of document Id. See example above.

Example

// return all matching entities
// within 10 kilometers radius
// from 32.1234 latitude and 23.4321 longitude coordinates
// sort results by distance from 32.1234 latitude and 23.4321 longitude point
List<House> results = session
    .Query<House>()
    .Spatial(
        factory => factory.Point(x => x.Latitude, x => x.Longitude),
        criteria => criteria.WithinRadius(10, 32.1234, 23.4321))
    .OrderByDistanceDescending(
        factory => factory.Point(x => x.Latitude, x => x.Longitude), 32.1234, 23.4321)
    .ToList();
// return all matching entities
// within 10 kilometers radius
// from 32.1234 latitude and 23.4321 longitude coordinates
// sort results by distance from 32.1234 latitude and 23.4321 longitude point
List<House> results = await asyncSession
    .Query<House>()
    .Spatial(
        factory => factory.Point(x => x.Latitude, x => x.Longitude),
        criteria => criteria.WithinRadius(10, 32.1234, 23.4321))
    .OrderByDistanceDescending(
        factory => factory.Point(x => x.Latitude, x => x.Longitude), 32.1234, 23.4321)
    .ToListAsync();
from Houses
where spatial.within(spatial.point(Latitude, Longitude), spatial.circle(10, 32.1234, 23.4321))
order by spatial.distance(spatial.point(Latitude, Longitude), spatial.point(32.1234, 23.4321)) desc

Remarks

Note

By default, distances are measured in kilometers.