Geospatial Queries

Geospatial queries return documents that contain location-data.

Introduction to Geospatial Querying

A geospatial query specifies a location, and returns each document that contains a proximity-match. A location is represented by means of longitude-latitude coordinate pairs.

This allows an application, based on the user’s input of a particular coordinate, address, or property name, to derive a list of points of interest that lie within a specified distance of the user-referenced location; and display these for the user’s benefit.

The location-data provided by a geospatial query can be either of the following:

  • A location, specified as a longitude-latitude coordinate pair; and a distance, in miles. The location determines the center of a circle whose radius-length is the specified distance. Documents are returned if they reference a location within the circle.

  • Two longitude-latitude coordinate pairs. These are respectively taken to indicate the top left and bottom right corners of a bounding box. Documents are returned if they reference a location within the box.

To be successful, a geospatial query must reference an index within which the geopoint type mapping has been applied to the field containing the target longitude-latitude coordinate pair.

Recognizing Target Data

The travel-sample bucket, provided for test and development, contains multiple documents that specify locations. For example, those that represent airports, such as airport_1254:

{
  "airportname": "Calais Dunkerque",
  "city": "Calais",
  "country": "France",
  "faa": "CQF",
  "geo": {
    "alt": 12,
    "lat": 50.962097,
    "lon": 1.954764
  },
  "icao": "LFAC",
  "id": 1254,
  "type": "airport",
  "tz": "Europe/Paris"
}

The geo field contains the lon and lat key-value pairs. Such a parent-field is accessed directly by a geospatial query: the internal long and lat child-fields are not explicitly specified. Moreover, any other child-field, such as alt, is ignored.

For information on installing the travel-sample bucket, see Sample Buckets.

Creating a Geospatial Index

To be successful, a geospatial query must reference an index that applies the geopoint type mapping to the field containing the longitude-latitude coordinate pair. This can be achieved by means of the Couchbase Web Console. Detailed instructions for setting up indexes, and specifying type mappings, are provided in Creating Indexes. For initial experimentation with geospatial querying, the geo field of documents within the travel-sample bucket can be specified as a child field of the default type mapping, as follows:

fts geopoint definition

The index so created can also be specified by means of the Couchbase REST API. See Demonstration Indexes for the body of the index to be used, and see Index-Creation with the REST API for information on using the REST syntax.

Creating a Query: Radius-Based

This section and the following provide examples of the query-bodies required to make geospatial queries with the Couchbase REST API. Note that more detailed information on performing queries with the Couchbase REST API can be found in Searching with the REST API; which shows how to use the full curl command, and how to incorporate query-bodies into it.

The following query-body specifies a longitude of -2.235143, and a latitude of 53.482358. The target-field geo is specified, as is a distance of 100 miles: this is the radius within which target-locations must reside, for their documents to be returned.

{
  "from": 0,
  "size": 10,
  "query": {
    "location": {
      "lon": -2.235143,
      "lat": 53.482358
     },
      "distance": "100mi",
      "field": "geo"
    },
  "sort": [
    {
      "by": "geo_distance",
      "field": "geo",
      "unit": "mi",
      "location": {
      "lon": -2.235143,
      "lat": 53.482358
      }
    }
  ]
}

The query contains a sort object, which specifies that the returned documents should be ordered in terms of their geo_distance from specified lon and lat coordinates: these values need not be identical to those specified in the query object.

A subset of formatted console output might appear as follows:

            .
            .
            .
"hits": [
  {
    "index": "geoIndex_61d8c796ef7f4360_acbbef99",
    "id": "landmark_17411",
    "score": 1.4045076008239446e-06,
    "sort": [
      " \u0001?E#9>N\f\"e"
    ]
  },
  {
    "index": "geoIndex_61d8c796ef7f4360_acbbef99",
    "id": "landmark_17409",
    "score": 1.4045076008239446e-06,
    "sort": [
      " \u0001?O~i*(kD,"
    ]
  },
  {
    "index": "geoIndex_61d8c796ef7f4360_acbbef99",
    "id": "landmark_17403",
    "score": 1.4045076008239446e-06,
    "sort": [
      " \u0001?Sg*|/t\u001f\u0002"
    ]
  },
  {
    "index": "geoIndex_61d8c796ef7f4360_acbbef99",
    "id": "hotel_17413",
    "score": 1.4045076008239446e-06,
    "sort": [
      " \u0001?U]S\\.e\u0002_"
   ]
  },
            .
            .
            .

Creating a Query: Box-Based

The following query body forms the top_left corner of a bounding box, specifying a longitude of -2.235143 and a latitude of 53.482358. This demonstrates use of an array to specify the coordinate pair: this option can be used interchangeably with that of using key-value pairs, whenever longitude and latitude are to be specified. Note that in the array, the lon value must precede the lat.

The bottom_right of the bounding box is formed by means of key-value pairs; specifying a longitude of 28.955043 and a latitude of 40.991862.

If a target data-location falls within the box, its document is returned. The results are specified to be sorted on name alone.

{
  "from": 0,
  "size": 10,
  "query": {
    "top_left": [-2.235143, 53.482358],
    "bottom_right": {
      "lon": 28.955043,
      "lat": 40.991862
     },
    "field": "geo"
  },
  "sort": [
    "name"
  ]
}

A subset of formatted output might appear as follows:

          .
          .
          .
"hits": [
  {
    "index": "geoIndex_61d8c796ef7f4360_acbbef99",
    "id": "landmark_17411",
    "score": 1.4045076008239446e-06,
    "sort": [
      " \u0001?E#9>N\f\"e"
    ]
  },
  {
    "index": "geoIndex_61d8c796ef7f4360_acbbef99",
    "id": "landmark_17409",
    "score": 1.4045076008239446e-06,
    "sort": [
      " \u0001?O~i*(kD,"
    ]
  },
  {
    "index": "geoIndex_61d8c796ef7f4360_acbbef99",
    "id": "landmark_17403",
    "score": 1.4045076008239446e-06,
    "sort": [
      " \u0001?Sg*|/t\u001f\u0002"
    ]
  },
  {
    "index": "geoIndex_61d8c796ef7f4360_acbbef99",
    "id": "hotel_17413",
    "score": 1.4045076008239446e-06,
    "sort": [
      " \u0001?U]S\\.e\u0002_"
    ]
  },
          .
          .
          .

Specifying Distance

Multiple unit-types can be used to express distance. These are listed in the table below, with the strings that specify them in REST queries.

Units Specify with

inches

in or inch

yards

yd or yards

feet

ft or feet

kilometers

km or kilometers

nautical miles

nm or nauticalmiles

millimeters

mm or millimeters

centimeters

cm or centimeters

miles

mi or miles

meters

m or meters