Características geoespaciales han demostrado a lo largo de los años que aumentan significativamente el compromiso de los usuarios. De hecho, nos hemos acostumbrado tanto a ello que ahora incluso esperamos que cualquier tipo de recomendación (noticias, restaurantes, productos) también se base en la ubicación. Hoy en día, la mayoría de las aplicaciones se basan principalmente en Radius. lo que, naturalmente, puede conducir a resultados imprecisos o subóptimos. En un mundo en el que las empresas compiten por la atención del usuario, la precisión puede ser un factor diferenciador clave, por eso la búsqueda basada en polígonos es cada vez más popular.
En este artículo, hablaremos de la búsqueda basada en polígonos en Couchbase, una característica que se ha añadido desde Couchbase 6.6
Qué es la búsqueda de polígonos geoespaciales
A consulta geoespacial especifica un área y devuelve cada documento que contenga una referencia a una ubicación dentro del área. Las áreas y las ubicaciones se representan mediante latitud–longitud pares de coordenadas.
Hay muchos tipos de geoespaciales consulta, Basado en el radio Las consultas (también conocidas como distancias puntuales) son las más utilizadas y también las más sencillas para empezar. Todo lo que necesitas es una coordenada y el radio del círculo:
1 |
GeoDistanceQuery geoDistanceQuery = BúsquedaQuery.geoDistancia( 37.379403,-121.967463, "10000"); |
En la búsqueda de recuadros delimitadores, debe especificar dos pares de coordenadas de latitud-longitud. Estas coordenadas indican respectivamente las esquinas superior izquierda e inferior derecha de un rectángulo. Los documentos se devuelven si hacen referencia a una ubicación dentro del área del rectángulo:
1 2 |
//coordenadas falsas GeoBoundingBoxQuery consulta = BúsquedaQuery.geoBoundingBox( 37.379403,-121.967463, 37.379403,-121.967463); |
Los dos métodos anteriores son excelentes cuando se necesitan resultados aproximados, pero no bastan cuando hay que limitar el área de búsqueda :
La búsqueda Geometría/Polígono geoespacial permite buscar documentos contenidos dentro de un objeto cerrado en forma de polígono definido por una secuencia de coordenadas. En la imagen anterior, por ejemplo, queremos limitar nuestra búsqueda únicamente a los documentos cuyas coordenadas se encuentren dentro del polígono que hemos definido, que en este caso representa un edificio.
Prácticamente no hay límite en el número de coordenadas/puntos que se pueden especificar en la consulta de polígonos, pero, como ocurre con cualquier otro motor de búsqueda, el rendimiento se reducirá naturalmente si hay que especificar polígonos muy complejos.
Caso de uso basado en polígonos geoespaciales
La búsqueda basada en polígonos (también denominada búsqueda geométrica) no se limita a las personas que analizan imágenes de satélite, sino que hay muchos casos de uso común que podrían beneficiarse de ella:
- Real State: Buscar oficinas/viviendas en un pueblo determinado o en una zona específica
- Juegos de azar: Aparición de objetos en zonas específicas (por ejemplo, diferentes tipos de pokemon que aparecen según el terreno en Pokemon Go).
- Analítica: Cuántas personas han pasado por una región específica (por ejemplo, cuántos conductores de Uber/Lyft han estado en el aeropuerto en un día determinado)
- Publicidad: Aumentar el CPC (coste por clic) cuando los usuarios se encuentran en un lugar específico (por ejemplo, un centro comercial).
- Ciudades inteligentes: Notificar a los ciudadanos de una región sobre una amenaza potencial (por ejemplo: granizada, inundaciones).
Crecimiento de la búsqueda geoespacial
Podemos demostrar indirectamente lo popular que se ha vuelto la búsqueda basada en la ubicación comparando el porcentaje de aplicaciones que solicitan permiso para acceder a la ubicación del usuario a lo largo de los años:
Según el gráfico anterior, en 2013 solo 11,68% de las aplicaciones móviles solicitaban acceso a la ubicación del usuario. Este otro informe sugiere que en 2014, casi 24% de las aplicaciones solicitaban la ubicación del usuario:
fuente: https://www.statista.com/statistics/486440/leading-google-play-app-permissions/
Si avanzamos rápido hasta 2020, este tercer informe ya sugiere que 95% de las apps en China solicitan acceso a la ubicación del usuario:
Creación de índices geoespaciales
Para esta demostración, necesitará este pequeño conjunto de datos de terremotos en EE.UU.. Puedes cargarlo rápidamente en Couchbase creando un bucket llamado terremotosy, a continuación, haga clic en Documentos -> Importar documentosseleccione el archivo earthquake.json y, a continuación, haga clic en Importar datos:
Ahora vamos a crear nuestro índice geo FTS. En primer lugar, vaya a la pestaña Buscar y haga clic en "Añadir índice". A continuación, especifique la siguiente configuración:
-
- Nombre: terremoto_idx
- Cubo: terremoto
- Asignaciones de tipos:
- Desmarcar por defecto
- Añade una nueva asignación de tipos denominada terremoto
- Insertar un campo hijo:
- Campo: geo
- Tipo: geopunto
- Se puede buscar como: geo
- Insertar un campo hijo:
Una vez que el Progreso del Índice alcanza 100% estamos listos para hacer nuestra primera búsqueda de polígonos.
Polígono / Búsqueda geométrica en acción
La búsqueda tiene dos requisitos principales: Los campos con coordenadas deben indexarse mediante la función geopuntos (como hicimos en la sesión anterior), y las coordenadas deben formar un polígono cerrado, lo que significa que la primera y la última coordenada deben ser iguales. He aquí un ejemplo de polígono válido:
1 2 |
[[-103.230791,37.0258202],[-108.4746292,43.1130542],[-116.2949697,44.9554792],[-123.7047084,41.8493514],[-122.8710938,38.7540833],[-120.0585938,34.6693585],[-117.9492188,34.0162419], [-115.1367188,32.694866],[-109.8632813,27.6056708],[-104.2382813,19.5597901],[-97.5585938,16.8045411],[-100.0195313,23.0797318],[-102.5664232,29.0188937],[-103.230791,37.0258202]] |
Si trazamos estas coordenadas en un mapa, esto es lo que obtendremos:
Fuente: https://www.keene.edu/campus/maps/tool/
Formatos de coordenadas admitidos
Se aceptan los siguientes formatos para las coordenadas de polígonos:
- Matriz única: [ "lat, lon", "lat, lon", "lat, lon", ...]
- Múltiples matrices: [ [ lon, lat], [ lon, lat], ... ]
- GeoJson: [ { "lat": 1, "lon": 1}, { "lat": 1, "lon": 1}, ... ]
- Geohash: [ "9q8zjbkp", "9q8yvvdh", "9q8yyp1e" ]
Búsqueda geoespacial mediante la API REST
Además de utilizar los SDK nativos, también puede utilizar la API REST de búsqueda de texto completo para realizar consultas geoespaciales utilizando el siguiente formato:
1 |
rizo -XPOST -H "Content-Type: application/json" -u nombre de usuario:contraseña http://dirección_ip:8094/api/index/index_name/query -d '{ "fields": [Fields_you_want_to_return], "query": {"campo": "target_geo_field", "polygon_points": [...]}}' |
He aquí un ejemplo real utilizando nuestro conjunto de datos e índice:
1 |
rizo -XPOST -H "Content-Type: application/json" -u Administrador:contraseña http://localhost:8094/api/index/earthquake_idx/query -d '{ "fields": ["Región"], "query": {"campo": "geo", "polygon_points": [[-103.230791,37.0258202],[-108.4746292,43.1130542],[-116.2949697,44.9554792], [-123.7047084,41.8493514],[-122.8710938,38.7540833],[-120.0585938,34.6693585],[-117.9492188,34.0162419], [-115.1367188,32.694866],[-109.8632813,27.6056708],[-104.2382813,19.5597901],[-97.5585938,16.8045411],[-100.0195313,23.0797318],[-102.5664232,29.0188937],[-103.230791,37.0258202]]}}' |
y aquí está la salida del comando anterior:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
{ "status":{ "total":1, "fallido":0, "con éxito":1 }, "solicitud":{ "consulta":{ "puntos_polígono":[ { "lon":-103.230791, "lat":37.0258202 }, { "lon":-108.4746292, "lat":43.1130542 }, { "lon":-116.2949697, "lat":44.9554792 }, { "lon":-123.7047084, "lat":41.8493514 }, { "lon":-122.8710938, "lat":38.7540833 }, { "lon":-120.0585938, "lat":34.6693585 }, { "lon":-117.9492188, "lat":34.0162419 }, { "lon":-115.1367188, "lat":32.694866 }, { "lon":-109.8632813, "lat":27.6056708 }, { "lon":-104.2382813, "lat":19.5597901 }, { "lon":-97.5585938, "lat":16.8045411 }, { "lon":-100.0195313, "lat":23.0797318 }, { "lon":-102.5664232, "lat":29.0188937 }, { "lon":-103.230791, "lat":37.0258202 } ], "campo":"geo" }, "tamaño":10, "de":0, "destacar":null, "campos":[ "Región ], "facetas":null, "explicar":falso, "clasificar":[ "-_score" ], "incluirLocalizaciones":falso, "buscar_después":null, "search_before":null }, "éxitos":[ { "índice":"earthquake_idx_61e3e23c5ecf99e1_acbbef99", "id":"8c70e570-5a6d-4f75-b409-f1bffd0417b5", "puntuación":0.0018446927534334827, "clasificar":[ "_score" ] }, { "índice":"earthquake_idx_61e3e23c5ecf99e1_acbbef99", "id":"8440a36e-fdb9-432e-b54b-13fbc1d482b4", "puntuación":0.0018446927534334827, "clasificar":[ "_score" ] }, { "índice":"earthquake_idx_61e3e23c5ecf99e1_acbbef99", "id":"c953d351-1811-4a2c-a2ba-8d0c94c9ffea", "puntuación":0.0018446927534334827, "clasificar":[ "_score" ] }, { "índice":"earthquake_idx_61e3e23c5ecf99e1_acbbef99", "id":"19fdf2ec-f53e-47ab-8bd3-70c1e6654c99", "puntuación":0.0018446927534334827, "clasificar":[ "_score" ] }, { "índice":"earthquake_idx_61e3e23c5ecf99e1_acbbef99", "id":"f95c8ec2-f58f-45f2-8c32-d7569e5d9b6b", "puntuación":0.0018446927534334827, "clasificar":[ "_score" ] }, { "índice":"earthquake_idx_61e3e23c5ecf99e1_acbbef99", "id":"9029d546-322f-4a2e-9919-fb85d2d17b42", "puntuación":0.0018446927534334827, "clasificar":[ "_score" ] }, { "índice":"earthquake_idx_61e3e23c5ecf99e1_acbbef99", "id":"5e0ae7e5-f825-44c6-b7d1-d398be7db081", "puntuación":0.0018446927534334827, "clasificar":[ "_score" ] }, { "índice":"earthquake_idx_61e3e23c5ecf99e1_acbbef99", "id":"1370a1f7-5f72-4c91-afcd-4ddef67e8a34", "puntuación":0.0018446927534334827, "clasificar":[ "_score" ] }, { "índice":"earthquake_idx_61e3e23c5ecf99e1_acbbef99", "id":"d9e4e8d9-6fbe-470b-b510-e688a1ccf1d3", "puntuación":0.0018446927534334827, "clasificar":[ "_score" ] }, { "índice":"earthquake_idx_61e3e23c5ecf99e1_acbbef99", "id":"b43ec13e-997d-45c7-954b-0433d4d6fa9e", "puntuación":0.0018446927534334827, "clasificar":[ "_score" ] } ], "total_hits":353, "max_score":0.0018446927534334827, "tomó":118981353, "facetas":null } |
Tenga en cuenta que debe especificar las coordenadas mediante el atributo puntos_polígono. También puede ampliar esta consulta para filtrar por otros atributos del documento (por ejemplo: Región, Magnitud, etc.)
Anillo geoespacial / Búsqueda en forma de donut
También puede especificar uno o más agujeros en su polígono en caso de que desee filtrar algunas áreas específicas:
Puedes conseguir algo como la imagen de arriba utilizando consultas booleanas:
1 2 3 4 5 6 7 8 9 10 11 12 |
{ ... "consulta": { "debe": { "Conjuntos": [{"campo":"geo", "puntos_polígono":{coordenadas_poligonales_exteriores}}] }, "must_not": { //singular nuestras disyunciones múltiples "disyuntos": [{"campo":"geo", "puntos_polígono":{coordenadas_poligonales_interiores}}] }, } } |
En resumen, basta con especificar las coordenadas de los polígonos dentro del campo "debe" y sus agujeros en el bloque "no_debe“.
Le recomiendo encarecidamente que utilice siempre Disyunciones al especificar sus agujeros, aunque también podría utilizar un Conjunción si tiene un solo agujero, el uso de la conjunción para múltiples agujeros potencialmente no filtrará sus datos correctamente (a menos que tenga documentos con coordenadas dentro de ambos agujeros). Si usted no tiene idea de lo que estoy hablando, consulte esta documentación sobre consultas compuestas.
Otras lecturas
Si está interesado en la búsqueda geográfica, le recomiendo encarecidamente que lea el documento documentación oficial. Si no conoce la búsqueda de texto completo, consulte este enlace vídeo en el que se muestra cómo crear una búsqueda similar a la de Netflix utilizando FTS.
También tenemos una serie de artículos en el blog de Couchbase que hablan sobre aspectos importantes de la búsqueda de texto completo:
- ¿Qué son los datos geoespaciales?
- Por qué deberías evitar el LIKE %
- Qué es el emparejamiento difuso y cómo utilizarlo correctamente
- Creación de una aplicación similar a Shazam para comprender cómo funcionan los tokenizadores y los filtros.
- Ejecución de consultas FTS en N1QL
- Análisis de textos en un motor de búsqueda de texto completo