Skip to main content

Geoqueries

A geoquery selects entities by where they are, whether inside an area, near a point, or crossing a line. You add it to an ordinary query as three parameters, and it runs against a GeoProperty of each entity. That is location unless you name another. This guide shows how to write one, how to combine it with other filters, and what the broker refuses.

The curl examples pass -g, so that curl doesn't read the brackets in coordinates as a range. In Rust the reference shape is a typed Shape, and the geoquery is built with geoquery::near_max, geoquery::within and the other start functions, so a ring that isn't closed is refused by try_new before any request leaves the machine.

Writing a geoquery​

A geoquery needs three parameters, and they go together. georel says how the entity's geometry must relate to the reference, geometry names the reference shape's GeoJSON type, and coordinates gives its positions.

The first asks for everything within 2 km of a point.

GET /ngsi-ld/v1/entities?type=Building&georel=near;maxDistance==2000&geometry=Point&coordinates=[2.3522,48.8566]

The next asks for everything inside a polygon.

GET /ngsi-ld/v1/entities?type=Building&georel=within&geometry=Polygon&coordinates=[[[2.3,48.84],[2.38,48.84],[2.38,48.88],[2.3,48.88],[2.3,48.84]]]

A polygon's ring is closed: its last position repeats the first.

The relations​

Each georel tests the entity's geometry against the reference.

  • near;maxDistance==d comes within d metres of the reference.
  • near;minDistance==d stays at least d metres away.
  • within lies inside the reference.
  • contains contains the reference.
  • intersects shares at least one point with the reference.
  • disjoint shares no point with the reference.
  • equals is the same shape as the reference.
  • overlaps shares part of its interior, with the same dimension.

near takes exactly one of the two distances. A band with both needs the near distance band extension.

Distances run over the earth's surface, between the nearest points of the two geometries, not between their centres. A building whose nearest wall is 100 m from the point is 100 m away, however large it is. Geometry and geoqueries gives the details.

Choosing the attribute​

geoproperty names the GeoProperty to test.

GET /ngsi-ld/v1/entities?type=Vehicle&geoproperty=operationSpace&georel=intersects&geometry=Point&coordinates=[2.3522,48.8566]

The name is expanded against the @context like any attribute name. An entity without that attribute doesn't match. If the attribute has several instances, one matching instance is enough.

Combining with other filters​

A geoquery is one more condition, and every condition has to hold.

GET /ngsi-ld/v1/entities?type=Vehicle&q=speed>30&georel=within&geometry=Polygon&coordinates=[[[2.3,48.84],[2.38,48.84],[2.38,48.88],[2.3,48.88],[2.3,48.84]]]

In a query sent as a body to POST /ngsi-ld/v1/entityOperations/query, the three parameters go into a geoQ object.

POST /ngsi-ld/v1/entityOperations/query
Content-Type: application/json

{
"type": "Query",
"entities": [
{
"type": "Building"
}
],
"geoQ": {
"georel": "near;maxDistance==1000",
"geometry": "Point",
"coordinates": [
2.2945,
48.8584
]
}
}

A subscription takes the same geoQ. It then notifies only about entities that match it. Subscriptions and notifications covers the filters.

Sorting by distance​

To get the nearest entities first, order by distance from a point with orderFrom. Ordering explains the distance sort and orderFrom.

Getting GeoJSON back​

Send Accept: application/geo+json and the answer is a GeoJSON FeatureCollection, one feature per entity, ready for a map.

GET /ngsi-ld/v1/entities?type=Building&georel=within&geometry=Polygon&coordinates=[[[2.3,48.84],[2.38,48.84],[2.38,48.88],[2.3,48.88],[2.3,48.84]]]
Accept: application/geo+json

Each feature's geometry comes from location, or from the GeoProperty that geometryProperty names. geometryProperty works only with this Accept.

Altitude​

A position can carry a third ordinate, the altitude. Andromeda stores it and gives it back, but a geoquery looks only at the footprint on the ground. Two entities at the same longitude and latitude are in the same place, whatever their height. Altitude has the rules for mixing flat and elevated positions.

What gets refused​

  • 400 BadRequestData for an incomplete geoquery, since georel, geometry and coordinates go together. Send all three or none.
  • 400 BadRequestData for near without a distance, or with both distances. Send exactly one of maxDistance and minDistance.
  • 400 BadRequestData for a malformed geometry, where the coordinates don't fit the geometry type, a ring isn't closed, or the type is GeometryCollection, which isn't supported. Strictness lists the geometry rules.