---
term: 'Consultas Geoespaciales & Indexación por Ubicación'
seoTitle: 'Consultas Geoespaciales e Indexación por Ubicación en BaaS'
headline: '¿Qué son las Consultas Geoespaciales?'
slug: consultas-geoespaciales
category: database
shortDefinition: 'Una consulta geoespacial es una búsqueda en la base de datos que filtra y ordena registros por ubicación — cerca de un punto, dentro de un radio o de un área.'
relatedTerms:
  - database-index
  - database-queries
  - relational-queries-document-databases
  - auto-generated-database-apis
contrastsWith:
  - database-index
faq:
  - question: '¿Qué es una consulta geoespacial?'
    answer: 'Una búsqueda en la base de datos cuyo filtro es espacial y no por valor: devuelve registros cerca de un punto, dentro de un radio o dentro de una caja o polígono, normalmente ordenados del más cercano al más lejano. La base guarda coordenadas como un tipo de primera clase — un GeoPoint de latitud y longitud — y un índice espacial responde la pregunta sin calcular la distancia a cada fila.'
  - question: '¿Qué es un campo GeoPoint?'
    answer: 'Un tipo de columna que guarda un par latitud/longitud, con latitud de -90 a 90 y longitud de -180 a 180. Como la base sabe que el campo es geográfico — y no solo dos floats —, puede indexarlo espacialmente y exponer operadores de distancia: a menos de X kilómetros o millas de aquí, dentro de esta bounding box, contenido en este polígono, ordenado por proximidad.'
  - question: '¿Cómo funciona un índice geoespacial estilo 2dsphere?'
    answer: 'Mapea la superficie curva de la Tierra en celdas ordenadas e indexables — celdas gruesas subdivididas en otras más finas —, de modo que la cercanía en el globo se vuelve adyacencia en el índice. Una consulta de proximidad inspecciona el puñado de celdas que cubren el área de búsqueda en vez de cada fila, y la geometría esférica mantiene las distancias honestas, incluso al cruzar el antimeridiano y cerca de los polos.'
  - question: '¿Por qué una búsqueda de cercanía es lenta sin índice geo?'
    answer: 'Porque sin él el motor debe calcular la distancia desde tu punto hasta cada fila y luego ordenarlo todo — un full scan disfrazado de trigonometría, repetido en cada solicitud. Un índice geo invierte el trabajo: va directo a las celdas que cubren el radio de búsqueda y toca solo candidatos plausibles. La brecha crece con el tamaño de la tabla, exactamente como con cualquier índice ausente, solo que más cara por fila.'
  - question: '¿Cuál es la diferencia entre una consulta near y una within?'
    answer: 'Una consulta near responde "¿qué está más cerca?" — ordena por distancia desde un punto y suele acotar el resultado con un limit o un radio máximo. Una consulta within responde "¿qué está adentro?" — filtra por contención en un radio, caja o polígono, sin implicar orden. Las listas de cafés cercanos son near; "tiendas en este viewport del mapa" y los chequeos de geofence son within.'
  - question: '¿Puedo combinar filtros geo con filtros comunes de consulta?'
    answer: 'Sí, y las features reales casi siempre lo hacen: a menos de 2 km *y* abierto ahora *y* con calificación superior a cuatro estrellas. La restricción geo se compone con filtros de igualdad, rango y pointer en una misma consulta. Cuida la interacción con la indexación — el índice espacial acota primero por ubicación, y los filtros comunes muy selectivos pueden merecer índice propio para que la consulta combinada siga siendo barata.'
  - question: '¿Qué tan precisas son las consultas por radio a grandes distancias?'
    answer: 'Los cálculos esféricos modelan la Tierra como una esfera, que difiere del elipsoide real hasta en aproximadamente un tercio de un por ciento — metros en distancias urbanas, y en general irrelevante para la lógica del producto. Lo que muerde antes es la precisión de los puntos almacenados: las coordenadas del GPS de un teléfono cargan metros de error al aire libre, y más en interiores. Para "encontrar X cerca", ambos efectos son ruido.'
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: 'Lanza el "cerca de mí" esta misma tarde'
  text: 'Back4app le da a cada clase campos GeoPoint con consultas por radio, por caja y por proximidad integradas en las APIs generadas automáticamente y en todos los SDKs — la feature de ubicación que suele exigir un desvío por una base de datos espacial se convierte en tres líneas de query.'
  linkText: 'Empieza gratis'
  linkUrl: 'https://www.back4app.com/signup'
author: 'Back4app Engineering'
publishedDate: '2026-09-04'
translationKey: geospatial-queries-indexing
---

**Una consulta geoespacial es una búsqueda en la base de datos que filtra y ordena registros por ubicación — cerca de un punto, dentro de un radio o de un área.** Es la que impulsa el pedido de feature que llega en el segundo mes de casi todo producto: *encontrar X cerca* — cafés, conductores, tiendas, otros usuarios. Y es el caso más claro de una clase de consulta que la [indexación B-tree común](/glossary/es/indice-de-base-de-datos/) no puede atender: la cercanía es bidimensional, y una estructura ordenada en una sola dimensión no la ve.

## Puntos clave

| Pregunta | Respuesta |
| --- | --- |
| El tipo de campo | GeoPoint — un par latitud/longitud que la base entiende |
| Las consultas | Near (ordenada por distancia), dentro del radio, dentro de la caja/polígono |
| El índice | Estilo 2dsphere: el globo mapeado en celdas indexables |
| Sin él | Distancia calculada a cada fila — un full scan con trigonometría |
| La feature canónica | "Encontrar X cerca", compuesta con filtros comunes |

## La consulta de cercanía, escrita y sentida

**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")
    }
}
```

La misma física en SQL, vía [PostGIS](https://postgis.net/) — y el índice que la hace viable:

```sql
-- Un índice espacial sobre la columna geography:
CREATE INDEX cafe_location_gix ON cafe USING GIST (location);

-- "Cafés a menos de 2 km, el más cercano primero":
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;
--  con el índice: toca solo las celdas que cubren el círculo de 2 km
--  sin él:        calcula una distancia para cada fila de la tabla
```

## Cómo el índice ve el globo

```mermaid
flowchart TB
  accTitle: Cómo un índice geo esférico responde una consulta por radio
  accDescr: La superficie de la Tierra se divide en celdas jerárquicas guardadas en orden. Una consulta por radio selecciona las pocas celdas que cubren el círculo de búsqueda, recorre solo los puntos candidatos dentro de ellas y calcula distancias exactas para esa lista corta.
  G["Globo dividido en<br/>celdas jerárquicas"] --> C1["Celda gruesa<br/>(escala de ciudad)"]
  C1 --> F1["Celdas finas cubriendo<br/>el círculo de 2 km"]
  F1 --> P["Puntos candidatos<br/>solo en esas celdas"]
  P --> D["Chequeo de distancia exacta<br/>+ orden por cercanía"]
```

Un [índice estilo 2dsphere](https://www.mongodb.com/docs/manual/geospatial-queries/) vuelve la cercanía indexable al mapear la superficie curva en celdas jerárquicas cuyo orden preserva la adyacencia — puntos cercanos en el globo caen en entradas cercanas del índice. Una consulta por radio se lee entonces como cualquier lookup en índice: identifica las pocas celdas que cubren el círculo, recorre sus candidatos, verifica las distancias exactas sobre esa lista corta. La geometría esférica — en lugar de la matemática de plano — mantiene los resultados correctos a escalas reales, al cruzar el antimeridiano y hacia los polos.

La regla de composición se sigue de la [mecánica común de consultas](/glossary/es/consultas-de-base-de-datos/): las restricciones geo se combinan libremente con filtros de igualdad, rango y pointer (`openNow == true` en las pestañas de arriba), y los filtros no-geo selectivos de las consultas calientes pueden merecer índices propios.

La paginación merece nota aparte, porque los resultados ordenados por distancia rompen el hábito del offset. Saltarse la primera página de una consulta near obliga al motor a reclasificar todo lo saltado, y un punto que se movió entre solicitudes puede barajar el orden bajo los pies del usuario. Los patrones más sólidos: ampliar el radio progresivamente para el "cargar más", o paginar por una clave estable dentro de un radio fijo. El orden por cercanía es un ranking sobre datos vivos — trata los límites de página como orientativos, no como filas de un libro contable.

## Near vs. within vs. consultas en plano

### ¿Qué consulta geo deberías usar?

| Forma de la consulta | Responde | Orden | Uso típico |
| --- | --- | --- | --- |
| Near (proximidad) | ¿Qué está más cerca de aquí? | Del más cercano al más lejano | Listas de "cafés cercanos", matching de conductores |
| Dentro del radio | ¿Qué está a menos de r km de aquí? | Ninguno implícito | Elegibilidad de entrega, alertas |
| Dentro de la caja | ¿Qué hay en este rectángulo? | Ninguno | Renderizado del viewport del mapa |
| Dentro del polígono | ¿Qué está dentro de esta forma? | Ninguno | Barrios, zonas, geofences |
| Plano (2d) | Lo mismo, en un plano proyectado | Varía | Mapas de juegos, planos de piso — no la Tierra |

La distinción near/within es lógica de producto, no pedantería: *near* es un ranking (acótalo con un limit y un radio máximo, o las ciudades densas devuelven miles de filas), *within* es un predicado (acompáñalo con la geometría del viewport o de la cerca). La fila del plano es la nota al pie honesta — para coordenadas que no están sobre una esfera, los índices esféricos son la herramienta equivocada.

## Casos de uso comunes

- **"Encontrar X cerca".** Cafés, gimnasios, cajeros, estaciones de carga — la lista de proximidad canónica, con radio acotado y el más cercano primero.
- **Matching y despacho.** Pasajeros con conductores, pedidos con repartidores — consultas near sobre GeoPoints actualizados con frecuencia.
- **Viewports de mapa.** Consultas dentro de la caja que alimentan los pines mientras el usuario arrastra el mapa — baratas, sin orden, del tamaño del viewport.
- **Geofencing.** Chequeos dentro del polígono para zonas de entrega, áreas de servicio y lógica disparada por ubicación.
- **Features sociales locales.** Gente cerca y eventos de este fin de semana, compuestos con filtros de privacidad y [relaciones por pointer](/glossary/es/joins-en-bases-de-documentos/).

## ¿Deberías usar consultas geo o precomputar regiones? Matriz de decisión

| Consulta en vivo con índice geo cuando… | Precomputa etiquetas de región cuando… |
| --- | --- |
| Los radios y formas varían por solicitud | Los límites son fijos (tiendas, zonas, distritos) |
| Los puntos se mueven a menudo (conductores, usuarios) | La pertenencia cambia rara vez |
| El orden por cercanía importa | Solo filtras por igualdad de región |
| Las formas son genuinamente espaciales | Una columna `region` simple lo responde todo |
| Tienes un índice espacial disponible | Estás agrupando, no midiendo |

La salida de emergencia importa: cuando toda consulta se reduce a "¿está en la zona A?", una columna de texto indexada común le gana a la maquinaria espacial — más barata, más simple y cubierta por B-trees comunes. La indexación espacial se gana su lugar exactamente cuando la geometría es dinámica: centros arbitrarios, puntos en movimiento, distancias reales.

## Limitaciones y trade-offs

- **Los índices geo son especialistas.** Sirven solo predicados espaciales; tus otros filtros siguen necesitando índices propios, y mantener un índice cuesta escrituras — el mismo impuesto, tarifa espacial.
- **Las consultas near sin límite son trampas.** Ordenar por cercanía en una ciudad densa sin radio máximo ni limit clasifica media tabla. Acota siempre la búsqueda.
- **Los puntos que se mueven escriben constantemente.** Ubicaciones de conductores en vivo significan actualizaciones de GeoPoint de alta frecuencia, cada una manteniendo el índice — agrupa en lotes o limita la frecuencia de las posiciones donde el producto lo permita.
- **Un punto por fila es el modelo base.** Una tienda con cinco sucursales son cinco registros; formas más ricas que puntos (rutas, áreas de cobertura) empujan hacia [bases de datos espaciales](https://en.wikipedia.org/wiki/Spatial_database) completas.
- **La precisión tiene pisos.** El error esfera-vs-elipsoide es despreciable, pero el ruido del GPS es de metros en un buen día — diseña la lógica del producto (zonas, umbrales) para tolerarlo.

## Consultas geoespaciales en Back4app

Back4app es una plataforma open-source de Backend as a Service (BaaS) que combina base de datos gestionada, APIs REST y GraphQL generadas automáticamente, autenticación, almacenamiento de archivos y funciones serverless con Cloud Code. GeoPoint es un tipo de columna nativo en el almacenamiento gestionado respaldado por MongoDB, y los operadores de proximidad, radio y caja — `withinKilometers`, `near`, `withinGeoBox` — vienen en las [APIs generadas automáticamente](/glossary/es/apis-generadas-automaticamente/) y en todos los SDKs, exactamente como los usan las pestañas de código de arriba. Los índices geo se gestionan junto con el resto de tu [estrategia de índices](/glossary/es/indice-de-base-de-datos/) en el dashboard, lo que convierte el habitual proyecto de infraestructura de "encontrar X cerca" en una decisión de esquema y tres líneas de query.
