New in version 12.0.0.
Geospatial data, or "geodata", specifies points and geometric objects on the Earth's surface. With the geodata types, you can create queries that check whether a given point is contained within a shape. For example, you can find all coffee shops within 15 km of a specified point.
Cambiado en la versión realm@12.3.0: Datos geoespaciales compatibles con Atlas Device Sync
Realm.js v12.3.0 y versiones posteriores añaden compatibilidad con datos geoespaciales en Atlas Device Sync. Esto permite suscribirse a consultas geoespaciales en un dominio sincronizado. Si intenta suscribirse a una consulta geoespacial con una versión anterior del SDK, recibirá un error de servidor con una escritura compensatoria. Para obtener más información sobre cómo administrar sus suscripciones de sincronización, consulte Geoespacial - SDK de React Native.
For more information on querying geospatial data with Device Sync, refer to Geospatial Data in the App Services documentation.
Geospatial Data Types
The SDK supports geospatial queries using the following data types:
GeoPoint
GeoCírculo
GeoBox
GeoPolígono
El SDK proporciona estos tipos de datos geoespaciales para simplificar la consulta de datos geoespaciales. No se pueden guardar estos tipos de datos directamente.
For information on how to persist geospatial data, refer to the Persist Geospatial Data section on this page.
Para realizar una query sobre datos geoespaciales, puede usar el operador geoWithin junto con RQL. El operador geoWithin toma la propiedad coordinates de un objeto incrustado que define el punto que estamos consultando, y una de las formas geoespaciales para verificar si ese punto está contenido dentro de la forma.
Nota
The format for querying geospatial data is the same, regardless of the shape of the geodata region.
GeoPoint
A GeoPoint defines a specific location on the Earth's surface. All of the geospatial data types use GeoPoints to define their location.
GeoPoint can be one of three types:
Un objeto con:
latitude: a number valuelongitude: a number valuealtitude: an optional number value
CanonicalGeoPoint: an interface that satisfies the GeoJSON specifications for a pointGeoPosition: an array with longitude, latitude, and an optional altitude
A GeoPoint is used only as a building block of the other shapes: GeoCircle, GeoBox, and GeoPolygon. These shapes, and the GeoPoint type, are used in queries, not for persistance.
Para guardar datos geoespaciales en realm, consulta Persistir datos geoespaciales en esta página.
GeoCírculo
Un GeoCírculo define un círculo en la superficie de la Tierra. Defina un GeoCircle proporcionando lo siguiente:
A
GeoPointfor the center of the circleUn número para la distancia (radio) del círculo
The radius distance uses radians as the unit of measure. The SDK provides the methods kmToRadians and miToRadians to convert kilometers or miles to radians.
El siguiente código muestra dos ejemplos de cómo crear un círculo:
import React from 'react'; import {View, Text} from 'react-native'; import {GeoCircle, GeoPoint, kmToRadians} from 'realm'; import {useQuery} from '@realm/react'; function Geocircle(): JSX.Element { // Define a GeoCircle const smallCircle: GeoCircle = { center: [-121.9, 47.3], // The GeoCircle radius is measured in radians. // This radian distance corresponds with 0.25 degrees. distance: 0.004363323, }; // Realm provides `kmToRadians` and `miToRadians` // to convert these measurements. Import the relevant // convenience method for your app's needs. const radiusFromKm = kmToRadians(44.4); // Define a GeoPoint within a GeoCircle const largeCircleCenter: GeoPoint = { longitude: -122.6, latitude: 47.8, }; const largeCircle: GeoCircle = { center: largeCircleCenter, distance: radiusFromKm, }; // Query geospatial data const companiesInSmallCircle = useQuery( Company, collection => collection.filtered('location geoWithin $0', smallCircle), [smallCircle], ); // Query geospatial data const companiesInLargeCircle = useQuery( Company, collection => collection.filtered('location geoWithin $0', largeCircle), [largeCircle], ); return ( <View> <Text>Small circle: {companiesInSmallCircle.length}</Text> <Text>Large circle: {companiesInLargeCircle.length}</Text> </View> ); }
The following image shows the results of creating two objects: a small circle and a large circle.

Queries against geospatial data return realm objects within the shapes you define. From the example above, this is the result of our queries:

GeoBox
A GeoBox defines a rectangle on the Earth's surface. You define the rectangle by specifying the bottom left (southwest) corner and the top right (northeast) corner. A GeoBox behaves in the same way as the corresponding GeoPolygon.
El siguiente ejemplo crea 2 cajas:
import React from 'react'; import {View, Text} from 'react-native'; import {GeoBox, GeoPoint} from 'realm'; import {useQuery} from '@realm/react'; function Geobox(): JSX.Element { // Define a GeoBox const largeBox: GeoBox = { bottomLeft: [-122.7, 47.3], topRight: [-122.1, 48.1], }; // Define GeoBox corners const smallBoxBottomLeft: GeoPoint = { longitude: -122.4, latitude: 47.5, }; const smallBoxTopRight: GeoPoint = { longitude: -121.8, latitude: 47.9, }; const smallBox: GeoBox = { bottomLeft: smallBoxBottomLeft, topRight: smallBoxTopRight, }; // Query geospatial data const companiesInLargeBox = useQuery( Company, collection => collection.filtered('location geoWithin $0', largeBox), [largeBox], ); // Query geospatial data const companiesInSmallBox = useQuery( Company, collection => collection.filtered('location geoWithin $0', smallBox), [smallBox], ); return ( <View> <Text>Small box: {companiesInSmallBox.length}</Text> <Text>Large box: {companiesInLargeBox.length}</Text> </View> ); }
La siguiente imagen muestra los resultados de crear dos objetos: una caja pequeña y una caja grande.

Queries against geospatial data return realm objects within the shapes you define. From the example above, this is the result of our queries:

GeoPolígono
Un GeoPolygon define un polígono en la superficie de la Tierra. Dado que un polígono es una figura cerrada, debes proporcionar al menos 4 puntos: 3 puntos para definir la forma del polígono y un cuarto para cerrarlo.
Importante
The fourth point in a polygon must be the same as the first point.
You can also exclude areas within a polygon by defining one or more "holes". A hole is another polygon whose bounds fit completely within the outer polygon. The following example creates 3 polygons: one is a basic polygon with 5 points, one is the same polygon with a single hole, and the third is the same polygon with two holes:
import React from 'react'; import {View, Text} from 'react-native'; import {GeoPolygon, GeoPoint} from 'realm'; import {useQuery} from '@realm/react'; function Geopolygon(): JSX.Element { // Define a basic GeoPolygon const basicPolygon: GeoPolygon = { outerRing: [ [-122.8, 48.0], [-121.8, 48.2], [-121.6, 47.6], [-122.0, 47.0], [-122.6, 47.2], [-122.8, 48.0], ], }; // Define a GeoPolygon with one hole const outerRing: GeoPoint[] = [ [-122.8, 48.0], [-121.8, 48.2], [-121.6, 47.6], [-122.0, 47.0], [-122.6, 47.2], [-122.8, 48.0], ]; const hole: GeoPoint[] = [ [-122.6, 47.8], [-122.2, 47.7], [-122.6, 47.4], [-122.5, 47.6], [-122.6, 47.8], ]; const polygonWithOneHole: GeoPolygon = { outerRing: outerRing, holes: [hole], }; // Add a second hole to the GeoPolygon const hole2: GeoPoint[] = [ { longitude: -122.05, latitude: 47.55, }, { longitude: -121.9, latitude: 47.55, }, { longitude: -122.1, latitude: 47.3, }, { longitude: -122.05, latitude: 47.55, }, ]; const polygonWithTwoHoles: GeoPolygon = { outerRing: outerRing, holes: [hole, hole2], }; // Query geospatial data const companiesInBasicPolygon = useQuery( Company, collection => collection.filtered('location geoWithin $0', basicPolygon), [basicPolygon], ); // Query geospatial data const companiesInPolygonWithTwoHoles = useQuery( Company, collection => collection.filtered('location geoWithin $0', polygonWithTwoHoles), [polygonWithTwoHoles], ); return ( <View> <Text>Basic polygon: {companiesInBasicPolygon.length}</Text> <Text> Polygon with two holes: {companiesInPolygonWithTwoHoles.length} </Text> </View> ); }
The following image shows the results of creating three objects: a polygon, a polygon with one hole, and a polygon with two holes.

Queries against geospatial data return realm objects within the shapes you define. From the example above, this is the result of our queries:

Persist Geospatial Data
Importante
Cannot Persist Geospatial Data Types
Actualmente, solo se pueden persistir datos geoespaciales. Los tipos de datos geoespaciales no pueden persistirse directamente. Por ejemplo, no se puede declarar una propiedad que sea del tipo GeoBox.
Estos tipos solo pueden utilizarse como argumentos para consultas geoespaciales.
Si desea conservar datos geoespaciales, deben cumplir con la especificación GeoJSON.
Create a GeoJSON-Compatible Class
To create a class that conforms to the GeoJSON spec, you:
Create an embedded realm object. For more information about embedded objects, refer to Embedded Objects - React Native SDK.
At a minimum, add the two fields required by the GeoJSON spec:
A field of type
double[]that maps to a "coordinates" (case sensitive) property in the realm schema.Un campo de tipo
stringque se asigna a una propiedad "tipo". El valor de este campo debe ser "punto".
To simplify geodata persistance, you can define a model that implements CanonicalGeoPoint, which already has the correct shape. The following example shows an embedded class named MyGeoPoint that is used to persist geospatial data.
A continuación, utilizas la clase MyGeoPoint personalizada en tu modelo de realm, como se muestra en el siguiente ejemplo. Añades instancias de tu clase al realm como cualquier otro modelo de Realm. Sin embargo, en este ejemplo, debido a que la clase MyGeoPoint no extiende Realm.Object, debemos especificar MyGeoPoint.schema al abrir el realm:
import React from 'react'; import Realm, {ObjectSchema, CanonicalGeoPoint, GeoPosition} from 'realm'; import {RealmProvider} from '@realm/react'; // Implement `CanonicalGeoPoint` // for convenience when persisting geodata. class MyGeoPoint implements CanonicalGeoPoint { coordinates!: GeoPosition; type = 'Point' as const; constructor(long: number, lat: number) { this.coordinates = [long, lat]; } static schema: ObjectSchema = { name: 'MyGeoPoint', embedded: true, properties: { type: 'string', coordinates: 'double[]', }, }; } class Company extends Realm.Object<Company> { _id!: number; location!: MyGeoPoint; static schema: ObjectSchema = { name: 'Company', properties: { _id: 'int', location: 'MyGeoPoint', }, primaryKey: '_id', }; } export const Geospatial = () => { return ( <View> {/* `MyGeoPoint` does not extend `Realm.Object`, so you pass only the `.schema` when opening the realm. */} <RealmProvider schema={[Company, MyGeoPoint.schema]}> <WriteGeospatialObjects /> </RealmProvider> </View> ); };
Guarda la clase incrustada.
Within RealmProvider, create your geospatial objects by combining the embedded class with classes that extend Realm.Object.
import React from 'react'; import {View} from 'react-native'; import {useEffect} from 'react'; import {useRealm, useQuery} from '@realm/react'; function WriteGeospatialObjects(): JSX.Element { const realm = useRealm(); const companies = useQuery(Company); useEffect(() => { if (!companies.length) { // Add geospatial objects to realm. writeNewCompany({_id: 6, location: new MyGeoPoint(-122.35, 47.68)}); writeNewCompany({_id: 9, location: new MyGeoPoint(-121.85, 47.9)}); } }, []); type CompanyProps = { _id: number; location: MyGeoPoint; }; const writeNewCompany = ({_id, location}: CompanyProps) => { // Add geospatial object to realm. realm.write(() => { realm.create(Company, { _id, location, }); }); }; return ( <View> <Geocircle /> <Geobox /> <Geopolygon /> </View> ); }
The following image shows the results of creating these two company objects.
