Make a Spatial Query
-
Documents that contain spatial data can be queried by spatial queries that employ geographical criteria.
You can use either Dynamic spatial query or Spatial index query.-
Dynamic spatial query
Make a dynamic spatial query on a collection (described below).
An auto-index will be created by the server. -
Spatial index query
Index your documents' spatial data in a static-index (see indexing spatial data) and then make a spatial query on this index (see query a spatial index).
-
-
To perform a spatial search,
use thespatial
method, which provides a wide range of spatial functionalities. -
When making a dynamic spatial query from Studio,
results are also displayed on the global map. See spatial queries map view.
-
In this page:
Search by radius
Use the within_radius
method to search for all documents containing spatial data that is located
within the specified distance from the given center point.
# This query will return all matching employee entities
# that are located within 20 kilometers radius
# from point (47.623473 latitude, -122.3060097 longitude).
# Define a query on Employees collection
employees_within_radius = list(
session.query(object_type=Employee)
# Call 'spatial' method
.spatial(
# Create 'PointField'
# Pass the path to document fields containing the spatial data
PointField("Address.Location.Latitude", "Address.Location.Longitude"),
# Set the geographical area in which to search for matching documents
# Call 'within_radius', pass the radius and the center points coordinates
lambda criteria: criteria.within_radius(20, 47.623473, -122.3060097),
)
)
// This query will return all matching employee entities
// that are located within 20 kilometers radius
// from point (47.623473 latitude, -122.3060097 longitude).
from Employees
where spatial.within(
spatial.point(Address.Location.Latitude, Address.Location.Longitude),
spatial.circle(20, 47.623473, -122.3060097)
)
Search by shape
-
Use the
relates_to_shape
method to search for all documents containing spatial data that is located
in the specified relation to the given shape. -
The shape is specified as either a circle or a polygon in a WKT format.
-
The relation to the shape can be one of:
WITHIN
,CONTAINS
,DISJOINT
,INTERSECTS
.
Circle
# This query will return all matching employee entities
# that are located within 20 kilometers radius
# from point (47.623473 latitude, -122.3060097 longitude).
# Define a query on Employees collection
employees_within_shape = list(
session.query(object_type=Employee)
# Call 'spatial' method
.spatial(
# Create 'PointField'
# Pass the path to document fields containing the spatial data
PointField("Address.Location.Latitude", "Address.Location.Longitude"),
# Set the geographical search criteria, call 'relates_to_shape'
lambda criteria: criteria.relates_to_shape(
# Specify the WKT string. Note: longitude is written FIRST
shape_wkt="CIRCLE(-122.3060097 47.623473 d=20)",
# Specify the relation between the WKT shape and the documents spatial data
relation=SpatialRelation.WITHIN,
# Optional: customize radius units (default is Kilometers)
units=SpatialUnits.MILES,
),
)
)
// This query will return all matching employee entities
// that are located within 20 kilometers radius
// from point (47.623473 latitude, -122.3060097 longitude).
from Employees
where spatial.within(
spatial.point(Address.Location.Latitude, Address.Location.Longitude),
spatial.wkt("CIRCLE(-122.3060097 47.623473 d=20)", "miles")
)
Polygon
# This query will return all matching company entities
# that are located within the specified polygon.
# Define a query on Companies collection
companies_within_shape = list(
session.query(object_type=Company)
# Call 'spatial' method
.spatial(
# Create 'PointField'
# Pass the path to document fields containing the spatial data
PointField("Address.Location.Latitude", "Address.Location.Longitude"),
# Set the geographical search criteria, call 'relates_to_shape'
lambda criteria: criteria.relates_to_shape(
# Specify the WKT string. Note: longitude is written FIRST
shape_wkt="""POLYGON ((
-118.6527948 32.7114894,
-95.8040242 37.5929338,
-102.8344151 53.3349629,
-127.5286633 48.3485664,
-129.4620208 38.0786067,
-118.7406746 32.7853769,
-118.6527948 32.7114894
))""",
# Specify the relation between the WKT shape and the documents spatial data
relation=SpatialRelation.WITHIN,
),
)
)
// This query will return all matching company entities
// that are located within the specified polygon.
from companies
where spatial.within(
spatial.point(Address.Location.Latitude, Address.Location.Longitude),
spatial.wkt("POLYGON ((
-118.6527948 32.7114894,
-95.8040242 37.5929338,
-102.8344151 53.3349629,
-127.5286633 48.3485664,
-129.4620208 38.0786067,
-118.7406746 32.7853769,
-118.6527948 32.7114894))")
)
Polygon rules
-
The polygon's coordinates must be provided in counterclockwise order.
-
The first and last coordinates must mark the same location to form a closed region.
WKT Polygon
Spatial sorting
-
Use
order_by_distance
ororder_by_distance_descending
to sort the results by distance from a given point. -
By default, distance is measured by RavenDB in kilometers.
The distance can be rounded to a specific range.
Order by distance
# Return all matching employee entities located within 20 kilometers radius
# from point (47.623473 latitude, -122.3060097 longitude)
# Sort the results by their distance from a specified point,
# the closest results will be listed first.
employees_sorted_by_distance = list(
session.query(object_type=Employee)
# Provide the query criteria:
.spatial(
PointField("Address.Location.Latitude", "Address.Location.Longitude"),
lambda criteria: criteria.within_radius(20, 47.623473, -122.3060097),
)
# Call 'order_by_distance'
.order_by_distance(
PointField("Address.Location.Latitude", "Address.Location.Longitude"), 47.623473, -122.3060097
)
)
// Return all matching employee entities located within 20 kilometers radius
// from point (47.623473 latitude, -122.3060097 longitude).
// Sort the results by their distance from a specified point,
// the closest results will be listed first.
from Employees
where spatial.within(
spatial.point(Address.Location.Latitude, Address.Location.Longitude),
spatial.circle(20, 47.623473, -122.3060097)
)
order by spatial.distance(
spatial.point(Address.Location.Latitude, Address.Location.Longitude),
spatial.point(47.623473, -122.3060097)
)
Order by distance descending
# Return all employee entities sorted by their distance from a specified point.
# The farthest results will be listed first.
employees_sorted_by_distance_desc = list(
session.query(object_type=Employee)
# Call 'order_by_distance_descending'
.order_by_distance_descending(
# Pass the path to document fields containing the spatial data
PointField("Address.Location.Latitude", "Address.Location.Longitude"),
# Sort the results by their distance (descending) from this point:
47.623473,
-122.3060097,
)
)
// Return all employee entities sorted by their distance from a specified point.
// The farthest results will be listed first.
from Employees
order by spatial.distance(
spatial.point(Address.Location.Latitude, Address.Location.Longitude),
spatial.point(47.623473, -122.3060097)
) desc
Sort results by rounded distance
# Return all employee entities.
# Results are sorted by their distance to a specified point rounded to the nearest 100 km interval.
# A secondary sort can be applied within the 100 km range, e.g. by field LastName.
employees_sorted_by_rounded_distance = list(
session.query(object_type=Employee)
# Call 'order_by_distance'
.order_by_distance(
# Pass the path to the document fields containing the spatial data
PointField("Address.Location.Latitude", "Address.Location.Longitude")
# Round up distance to 100 km
.round_to(100),
# Sort the results by their distance from this point:
47.623473,
-122.3060097,
).order_by(
"LastName"
) # todo gracjan: check if its possible to order by again without then_by
# todo reeb: skip this example for now, we'll get back to it later on
# A secondary sort can be applied
)
pass
o:
gion spatial_7
spatial(
self,
field_name_or_field: Union[str, DynamicSpatialField],
clause: Callable[[SpatialCriteriaFactory], SpatialCriteria],
..
// Return all employee entities.
// Results are sorted by their distance to a specified point rounded to the nearest 100 km interval.
// A secondary sort can be applied within the 100 km range, e.g. by field LastName.
from Employees
order by spatial.distance(
spatial.point(Address.Location.Latitude, Address.Location.Longitude),
spatial.point(47.623473, -122.3060097),
100
), LastName
Get resulting distance
- The distance is available in the
@spatial
metadata property within each result. -
Note the following difference between the underlying search engines:
- When using Lucene:
This metadata property is always available in the results. - When using Corax:
In order to enhance performance, this property is not included in the results by default.
To get this metadata property you must set the Indexing.Corax.IncludeSpatialDistance configuration value to true.
Learn about the available methods for setting an indexing configuration key in this indexing-configuration article.
- When using Lucene:
# Get the distance of the results:
# ================================
# Call 'get_metadata_for', pass an entity from the resulting employees list
metadata = session.advanced.get_metadata_for(employees_sorted_by_distance[0])
# The distance is available in the '@spatial' metadata property
spatial_results = metadata["@spatial"]
distance = spatial_results["Distance"] # The distance of the entity from the queried location
latitude = spatial_results["Latitude"] # The entity's latitude value
longitude = spatial_results["Longitude"] # The entity's longitude value
Spatial API
spatial
def spatial(
self,
field_name_or_field: Union[str, DynamicSpatialField],
clause: Callable[[SpatialCriteriaFactory], SpatialCriteria],
): ...
Parameters | Type | Description |
---|---|---|
field_name_or_field | Union[str, DynamicSpatialField] |
Str - Path to spatial field in an index (when querying an index)-or- DynamicSpatialField - Object that contains the document's spatial fields, either PointField or WktField (when making a dynamic query). |
clause | Callable[[SpatialCriteriaFactory], SpatialCriteria] |
Callback taking leverage of SpatialCriteriaFactory that comes as an argument, allowing to build SpatialCriteria. |
DynamicSpatialField
class PointField(DynamicSpatialField):
def __init__(self, latitude: str, longitude: str): ...
class WktField(DynamicSpatialField):
def __init__(self, wkt: str): ...
Parameters | Type | Description |
---|---|---|
latitude | str |
Path to a document point field that contains the latitude |
longitude | str |
Path to a document point field that contains the longitude |
wkt | str |
Path to a document wkt field that contains the WKT string |
SpatialCriteria
def relates_to_shape(
self,
shape_wkt: str,
relation: SpatialRelation,
units: SpatialUnits = None,
dist_error_percent: Optional[float] = constants.Documents.Indexing.Spatial.DEFAULT_DISTANCE_ERROR_PCT,
) -> SpatialCriteria: ...
def intersects(
self,
shape_wkt: str,
units: Optional[SpatialUnits] = None,
dist_error_percent: Optional[float] = constants.Documents.Indexing.Spatial.DEFAULT_DISTANCE_ERROR_PCT,
) -> SpatialCriteria: ...
def contains(
self,
shape_wkt: str,
units: Optional[SpatialUnits] = None,
dist_error_percent: Optional[float] = constants.Documents.Indexing.Spatial.DEFAULT_DISTANCE_ERROR_PCT,
) -> SpatialCriteria: ...
def disjoint(
self,
shape_wkt: str,
units: Optional[SpatialUnits] = None,
dist_error_percent: Optional[float] = constants.Documents.Indexing.Spatial.DEFAULT_DISTANCE_ERROR_PCT,
) -> SpatialCriteria: ...
def within(
self,
shape_wkt: str,
units: Optional[SpatialUnits] = None,
dist_error_percent: Optional[float] = constants.Documents.Indexing.Spatial.DEFAULT_DISTANCE_ERROR_PCT,
) -> SpatialCriteria: ...
def within_radius(
self,
radius: float,
latitude: float,
longitude: float,
radius_units: Optional[SpatialUnits] = None,
dist_error_percent: Optional[float] = constants.Documents.Indexing.Spatial.DEFAULT_DISTANCE_ERROR_PCT,
) -> SpatialCriteria: ...
Parameter | Type | Description |
---|---|---|
shape_wkt | str |
WKT-based shape used in query criteria |
relation | SpatialRelation |
Relation of the shape to the spatial data in the document/index. Can be WITHIN , CONTAINS , DISJOINT , INTERSECTS |
units / radius_units | SpatialUnits |
Determines if circle or shape should be calculated in KILOMETERS or MILES .By default, distances are measured in kilometers. |
dist_error_percent (Optional) | float |
Maximum distance error tolerance in percents. Default: 0.025 |
radius / latitude / longitude | float |
Used to define a radius of a circle |
order_by_distance
, order_by_distance_wkt
# From point & rounding
def order_by_distance(
self,
field_or_field_name: Union[str, DynamicSpatialField],
latitude: float,
longitude: float,
round_factor: Optional[float] = 0.0,
) -> DocumentQuery[_T]: ...
# From center of WKT shape
def order_by_distance_wkt(
self, field_or_field_name: Union[str, DynamicSpatialField], shape_wkt: str
) -> DocumentQuery[_T]: ...
order_by_distance_descending
, order_by_distance_descending_wkt
# From point & rounding
def order_by_distance_descending(
self,
field_or_field_name: Union[str, DynamicSpatialField],
latitude: float,
longitude: float,
round_factor: Optional[float] = 0.0,
) -> DocumentQuery[_T]: ...
# From center of WKT shape
def order_by_distance_descending_wkt(
self, field_or_field_name: Union[str, DynamicSpatialField], shape_wkt: str
) -> DocumentQuery[_T]: ...
Parameter | Type | Description |
---|---|---|
field_or_field_name | Union[str, DynamicSpatialField] |
Str - Path to spatial field in an index (when querying an index)-or- DynamicSpatialField - Object that contains the document's spatial fields, either PointField or WktField (when making a dynamic query). |
latitude | float |
The latitude of the point from which the distance is measured |
longitude | float |
The longitude of the point from which the distance is measured |
round_factor (Optional) | float |
A distance interval in kilometers. The distance from the point is rounded up to the nearest interval. The results within the same interval can be sorted by a secondary order. If no other order was specified, then by ascending order of document Id. |
shape_wkt | str |
WKT-based shape used in query criteria |