---
term: 'Geospatial Queries & Location-Based Indexing in BaaS'
seoTitle: 'Geospatial Queries & Location-Based Indexing in BaaS'
headline: 'What are Geospatial Queries?'
slug: geospatial-queries-indexing
category: database
shortDefinition: 'A geospatial query is a database lookup that filters and sorts records by location — near a point, within a radius, or inside an area.'
relatedTerms:
  - database-index
  - database-queries
  - relational-queries-document-databases
  - auto-generated-database-apis
contrastsWith:
  - database-index
faq:
  - question: 'What is a geospatial query?'
    answer: 'A database lookup whose filter is spatial rather than by value: return records near a point, within a radius, or inside a box or polygon, usually sorted nearest-first. The database stores coordinates as a first-class type — a GeoPoint of latitude and longitude — and a spatial index answers the question without computing the distance to every row.'
  - question: 'What is a GeoPoint field?'
    answer: 'A column type holding a latitude/longitude pair, with latitude from -90 to 90 and longitude from -180 to 180. Because the database knows the field is geographic — not just two floats — it can index it spatially and expose distance operators: within kilometers or miles of here, inside this bounding box, contained in this polygon, sorted by proximity.'
  - question: 'How does a 2dsphere-style geo index work?'
    answer: 'It maps the curved surface of the Earth onto sorted, indexable cells — coarse cells subdivided into finer ones — so that nearness on the globe becomes adjacency in the index. A near query inspects the handful of cells covering the search area instead of every row, and spherical geometry keeps distances honest, including across the antimeridian and near the poles.'
  - question: 'Why is a nearby search slow without a geo index?'
    answer: 'Because without one the engine must compute the distance from your point to every row, then sort the lot — a full scan wearing trigonometry, repeated on every request. A geo index inverts the work: it walks straight to the cells covering the search radius and touches only plausible candidates. The gap widens with table size, exactly like any missing index, only costlier per row.'
  - question: 'What is the difference between a near query and a within query?'
    answer: 'A near query answers "what is closest?" — it sorts by distance from a point and typically caps results with a limit or maximum radius. A within query answers "what is inside?" — it filters by containment in a radius, box, or polygon and implies no ordering. Nearest-cafes lists are near queries; "stores in this map viewport" and geofence checks are within queries.'
  - question: 'Can I combine geo filters with ordinary query filters?'
    answer: 'Yes, and real features almost always do: within 2 km *and* open now *and* rated above four stars. The geo constraint composes with equality, range, and pointer filters in one query. Mind the interplay with indexing — the spatial index narrows by location first, and highly selective ordinary filters may deserve their own index so the combined query stays cheap.'
  - question: 'How accurate are radius queries at large distances?'
    answer: 'Spherical calculations model the Earth as a sphere, which differs from the true ellipsoid by up to roughly a third of a percent — meters over city distances, and usually irrelevant to product logic. What bites earlier is precision of the stored points themselves: coordinates from phone GPS carry meters of error outdoors and more indoors. For "find nearby X" both effects are noise.'
codeLanguages: [javascript, dart, swift, kotlin]
externalAuthorities:
  - name: 'MongoDB geospatial queries'
    url: 'https://www.mongodb.com/docs/manual/geospatial-queries/'
  - name: 'Parse SDK guide — GeoPoints'
    url: 'https://docs.parseplatform.org/js/guide/'
  - name: 'PostGIS — spatial extension for PostgreSQL'
    url: 'https://postgis.net/'
  - name: 'Spatial database (Wikipedia)'
    url: 'https://en.wikipedia.org/wiki/Spatial_database'
cta:
  title: 'Ship "find nearby" this afternoon'
  text: 'Back4app gives every class GeoPoint fields with radius, box, and proximity queries built into the auto-generated APIs and every SDK — the location feature that usually demands a spatial-database detour becomes three lines of query code.'
  linkText: 'Start building free'
  linkUrl: 'https://www.back4app.com/signup'
author: 'Back4app Engineering'
publishedDate: '2026-08-05'
translationKey: geospatial-queries-indexing
---

**A geospatial query is a database lookup that filters and sorts records by location — near a point, within a radius, or inside an area.** It powers the feature request that arrives in almost every product's second month: *find nearby X* — cafes, drivers, stores, other users. And it is the clearest case of a query class that ordinary [B-tree indexing](/glossary/database-index/) cannot serve: nearness is two-dimensional, and a structure sorted on one dimension cannot see it.

## Key takeaways

| Question | Answer |
| --- | --- |
| The field type | GeoPoint — a latitude/longitude pair the database understands |
| The queries | Near (sorted by distance), within-radius, within-box/polygon |
| The index | 2dsphere-style: the globe mapped to indexable cells |
| Without it | Distance computed to every row — a full scan with trigonometry |
| The canonical feature | "Find nearby X," composed with ordinary filters |

## The nearby query, created and felt

**JavaScript:**

```javascript
// JavaScript / Node.js — Back4app JS SDK
// "Find cafes within 2 km, nearest first" — the canonical geo query
const here = new Parse.GeoPoint({ latitude: 40.7484, longitude: -73.9857 });

const query = new Parse.Query('Cafe');
query.withinKilometers('location', here, 2); // radius filter, nearest-first
query.equalTo('openNow', true);              // geo + ordinary filters compose
query.limit(20);
const cafes = await query.find();

cafes.forEach((c) => {
  const km = here.kilometersTo(c.get('location'));
  console.log(`${c.get('name')} — ${km.toFixed(2)} km away`);
});
```

**Flutter:**

```dart
// Flutter / Dart — Back4app Flutter SDK
// "Find cafes within 2 km, nearest first" — the canonical geo query
final here = ParseGeoPoint(latitude: 40.7484, longitude: -73.9857);

final query = QueryBuilder<ParseObject>(ParseObject('Cafe'))
  ..whereWithinKilometers('location', here, 2) // radius filter, nearest-first
  ..whereEqualTo('openNow', true)              // geo + ordinary filters compose
  ..setLimit(20);
final response = await query.query();

for (final result in response.results ?? []) {
  final cafe = result as ParseObject;
  final loc = cafe.get<ParseGeoPoint>('location');
  print('${cafe.get<String>('name')} at '
      '${loc?.latitude}, ${loc?.longitude}');
}
```

**Swift:**

```swift
// iOS / Swift — Back4app Swift SDK
// "Find cafes within 2 km, nearest first" — the canonical geo query
let here = try ParseGeoPoint(latitude: 40.7484, longitude: -73.9857)

let query = Cafe.query(
  withinKilometers(key: "location", geoPoint: here, distance: 2),
  "openNow" == true                 // geo + ordinary filters compose
).limit(20)

query.find { result in
  if case .success(let cafes) = result {
    for cafe in cafes {
      print("\(cafe.name ?? "?") — \(String(describing: cafe.location))")
    }
  }
}
```

**Kotlin:**

```kotlin
// Android / Kotlin — Back4app Android SDK
// "Find cafes within 2 km, nearest first" — the canonical geo query
val here = ParseGeoPoint(40.7484, -73.9857)

val query = ParseQuery.getQuery<ParseObject>("Cafe")
query.whereWithinKilometers("location", here, 2.0) // radius, nearest-first
query.whereEqualTo("openNow", true)                // geo + filters compose
query.limit = 20

query.findInBackground { cafes, e ->
    if (e == null) cafes.forEach { cafe ->
        val loc = cafe.getParseGeoPoint("location")
        val km = loc?.distanceInKilometersTo(here)
        println("${cafe.getString("name")} — ${"%.2f".format(km)} km away")
    }
}
```

The same physics in SQL, via [PostGIS](https://postgis.net/) — and the index that makes it viable:

```sql
-- A spatial index over the geography column:
CREATE INDEX cafe_location_gix ON cafe USING GIST (location);

-- "Cafes within 2 km, nearest first":
SELECT name, ST_Distance(location, ST_MakePoint(-73.9857, 40.7484)::geography) AS meters
FROM cafe
WHERE ST_DWithin(location, ST_MakePoint(-73.9857, 40.7484)::geography, 2000)
ORDER BY location <-> ST_MakePoint(-73.9857, 40.7484)::geography
LIMIT 20;
--  with the index: touches only cells covering the 2 km circle
--  without it:     computes a distance for every row in the table
```

## How the index sees the globe

```mermaid
flowchart TB
  accTitle: How a spherical geo index answers a radius query
  accDescr: The Earth's surface is divided into hierarchical cells stored in sorted order. A radius query selects the few cells covering the search circle, scans only candidate points within them, and computes exact distances for that short list.
  G["Globe divided into<br/>hierarchical cells"] --> C1["Coarse cell<br/>(city scale)"]
  C1 --> F1["Finer cells covering<br/>the 2 km circle"]
  F1 --> P["Candidate points<br/>in those cells only"]
  P --> D["Exact distance check<br/>+ sort nearest-first"]
```

A [2dsphere-style index](https://www.mongodb.com/docs/manual/geospatial-queries/) makes nearness indexable by mapping the curved surface onto hierarchical cells whose sorted order preserves adjacency — points close on the globe land in nearby index entries. A radius query then reads like any index lookup: identify the few cells covering the circle, scan their candidates, verify exact distances on that short list. Spherical geometry — rather than flat-plane math — keeps results correct at real-world scales, across the antimeridian, and toward the poles.

The composition rule follows from ordinary [query mechanics](/glossary/database-queries/): geo constraints combine freely with equality, range, and pointer filters (`openNow == true` in the tabs above), and the selective non-geo filters in hot queries may deserve indexes of their own.

Pagination deserves a special note, because distance-sorted results break the offset habit. Skipping past page one of a near query forces the engine to re-rank everything skipped, and a point that moved between requests can shuffle the order under the user's feet. The sturdier patterns: widen the radius progressively for "load more," or paginate on a stable key within a fixed radius. Nearest-first is a ranking over live data — treat page boundaries as advisory, not as rows in a ledger.

## Near vs. within vs. flat-plane queries

### Which geo query should you use?

| Query shape | Answers | Ordering | Typical use |
| --- | --- | --- | --- |
| Near (proximity) | What is closest to here? | Nearest-first | "Nearby cafes" lists, matching drivers |
| Within radius | What is inside r km of here? | None implied | Delivery eligibility, alerts |
| Within box | What is in this rectangle? | None | Map viewport rendering |
| Within polygon | What is inside this shape? | None | Neighborhoods, zones, geofences |
| Flat-plane (2d) | Same, on a projected plane | Varies | Game maps, floor plans — not the Earth |

The near/within distinction is product logic, not pedantry: *near* is a ranking (cap it with a limit and a maximum radius, or dense cities return thousands of rows), *within* is a predicate (pair it with the viewport or fence geometry). The flat-plane row is the honest footnote — for coordinates that are not on a sphere, spherical indexes are the wrong tool.

## Common use cases

- **"Find nearby X."** Cafes, gyms, ATMs, charging stations — the canonical proximity list, radius-capped and nearest-first.
- **Matching and dispatch.** Riders to drivers, jobs to couriers — near queries over frequently updated GeoPoints.
- **Map viewports.** Within-box queries feeding pins as the user pans — cheap, unordered, viewport-sized.
- **Geofencing.** Within-polygon checks for delivery zones, service areas, and location-triggered logic.
- **Local social features.** People-nearby and events-this-weekend, composed with privacy filters and [pointer-based relationships](/glossary/relational-queries-document-databases/).

## Should you use geo queries or precompute regions? A decision matrix

| Query live with a geo index when… | Precompute region labels when… |
| --- | --- |
| Radii and shapes vary per request | Boundaries are fixed (stores, zones, districts) |
| Points move often (drivers, users) | Membership changes rarely |
| Nearest-first ordering matters | You only ever filter by region equality |
| Shapes are genuinely spatial | A simple `region` column answers everything |
| You have a spatial index available | You are grouping, not measuring |

The escape hatch matters: when every query reduces to "in zone A?", a plain indexed string column beats spatial machinery — cheaper, simpler, and covered by ordinary B-trees. Spatial indexing earns its keep exactly when the geometry is dynamic: arbitrary centers, moving points, real distances.

## Limitations and trade-offs

- **Geo indexes are specialists.** They serve spatial predicates only; your other filters still need their own indexes, and index maintenance costs writes — same tax, spatial rate.
- **Unbounded near queries are footguns.** Nearest-first over a dense city without a radius cap or limit ranks half the table. Always bound the search.
- **Moving points write constantly.** Live driver locations mean high-frequency GeoPoint updates, each maintaining the index — batch or throttle position updates where product allows.
- **One point per row is the base model.** A store with five branches is five records; shapes richer than points (routes, coverage areas) push toward fuller [spatial databases](https://en.wikipedia.org/wiki/Spatial_database).
- **Precision has floors.** Sphere-vs-ellipsoid error is negligible, but GPS noise is meters on a good day — design product logic (zones, thresholds) to tolerate it.

## Geospatial queries on Back4app

Back4app is an open-source Backend-as-a-Service (BaaS) platform that combines a managed database, auto-generated REST and GraphQL APIs, authentication, file storage, and Cloud Code serverless functions. GeoPoint is a native column type on the managed MongoDB-backed store, and the proximity, radius, and box operators — `withinKilometers`, `near`, `withinGeoBox` — ship in the [auto-generated APIs](/glossary/auto-generated-database-apis/) and every SDK, exactly as the code tabs above use them. Geo indexes are managed alongside the rest of your [index strategy](/glossary/database-index/) in the dashboard, which turns the usual "find nearby X" infrastructure project into a schema decision and three lines of query.
