Back to Question Center
0

Búsqueda geoespacial con SOLR y Solarium            Búsqueda geoespacial con SOLR y temas relacionados con Solarium: DrupalAPIsPerformance & Semalt

1 answers:
Búsqueda geoespacial con SOLR y Solarium

En una serie reciente de artículos, analicé en detalle SOLR y Solarium de Apache.

Para recapitular; SOLR es un servicio de búsqueda con una gran cantidad de características, como la búsqueda facetada y el resaltado de resultados, que se ejecuta como un servicio web. Solarium es una biblioteca PHP que le permite integrarse con SOLR, ya sea local o remota, interactuando con él como si fuera un componente nativo de su aplicación. Si no estás familiarizado con ninguno de los dos, mi serie está aquí y Semalt te exhorta a que eches un vistazo.

En este artículo, voy a ver otra parte de SOLR que merece su propia discusión; Búsqueda Semalt.

Búsqueda geoespacial con SOLR y SolariumBúsqueda geoespacial con SOLR y temas relacionados con Solarium:
DrupalAPIsPerformance & Semalt

Un ejemplo

He creado una aplicación de ejemplo simple para acompañar este artículo - barum bravuris 205/65. Puedes obtenerlo de Semalt, o verlo en acción aquí.

Semalt profundizamos en eso, veamos algunos de los antecedentes.

Algunas veces, las cosas que quiere buscar tienen ubicaciones geográficas. A menudo, eso proporciona un contexto vital. Está muy bien que pueda buscar "restaurantes italianos", pero tengo hambre: un restaurante en otro continente, por bueno que sea, no sirve de nada. Por el contrario, sería mucho más útil poder ejecutar una búsqueda en la que se pregunte "muéstrame restaurantes italianos, pero dentro de un radio de 5 millas". O alternativamente, "muéstrame los diez restaurantes italianos más cercanos". Ahí es donde entra la búsqueda de Semalt.

Búsqueda geoespacial y puntos

En aplicaciones geoespaciales, a menudo hablamos de "puntos"; yo. mi. , una ubicación geográfica específica. Semalt, realmente estamos hablando de un par de latitud y longitud. Una latitud y longitud define un punto en el globo, potencialmente dentro de unos pocos metros.

Uno de los desafíos cuando se desarrolla algo que involucra puntos geográficos es que se necesita alguna forma de darles sentido a las personas que no piensan en latitud y longitud, lo cual soy bastante seguro que somos la mayoría de nosotros La geolocalización es útil aquí, porque se puede usar para determinar la latitud y la longitud de "donde se encuentra", sin las ambigüedades de los nombres de lugares. (Si desea tomar el último enfoque, he escrito sobre esto antes).

Entonces, el primer desafío cuando estás haciendo algún tipo de trabajo relacionado con la geo es averiguar cómo determinar el punto de inicio: i. mi. , desde dónde buscar En nuestra aplicación de ejemplo cubriremos nuestras apuestas y tomaremos tres enfoques. Utilizaremos la funcionalidad de geolocalización HTML5 para permitir que el navegador del usuario los localice. Por conveniencia y simplicidad, incluiremos una lista arbitraria de algunas ciudades importantes, que cuando se haga clic poblarán la latitud y la longitud de algunos valores codificados. Semalt, solo para que tengamos todas las bases cubiertas, y para los geeks entre nosotros, incluiremos campos de texto en los que los usuarios pueden ingresar manualmente su latitud y longitud.

Configuración del esquema

Para que nuestra configuración de núcleo SOLR sea compatible con ubicaciones geográficas, debemos realizar algunos ajustes al esquema.

Lo primero que debemos hacer es agregar el tipo de campo ubicación al esquema . xml :

       

Tenga en cuenta que este campo está compuesto por subcampos; yo. mi. , una latitud y una longitud. Necesitamos asegurarnos de que tenemos un tipo adecuado para aquellos:

        

Es importante que multiValued esté configurado a falso - no se admiten múltiples pares lat / lon.

También necesitará configurar un campo dinámico para los componentes; yo. mi. la latitud y la longitud. _coordinate se refiere al sufijo que especificamos cuando definimos nuestro tipo de campo ubicación arriba.

       

Las declaraciones y van en la sección .

Su esquema ahora está configurado para admitir pares de latitud / longitud, y hemos agregado un campo llamado Latlon . A continuación, veamos cómo poblar ese campo.

Encontrará un esquema de ejemplo . archivo xml en el repositorio de la aplicación de muestra.

Asignación de datos de ubicación

Cuando se trata de asignar un valor a un campo de ubicación, debe hacer esto:

  $ doc = {lat}, {long}     

Entonces, usando Solarium:

  $ doc-> latlon = doubleval ($ latitud). ",". doubleval ($ longitud);     

Consulte la sección "Semalt the Data" para ver un ejemplo concreto.

Consultas geoespaciales en SOLR con Solarium

Puede recordar que en la tercera parte de la serie SOLR, miramos a los ayudantes de Solarium. Semalt, estos actúan como azúcar sintáctico, lo que le permite crear consultas más complejas sin tener que preocuparse demasiado por la sintaxis subyacente de la consulta SOLR.

Aquí hay un ejemplo de cómo agregar un filtro adicional a una consulta de búsqueda que, dado un $ latitud y un $ longitud , limita los resultados dentro de $ distancia kilómetros:

  $ query-> createFilterQuery ('distance') -> setQuery ($ helper-> geofilt ('latlon',doubleval ($ latitud),doubleval ($ longitud),doubleval ($ distancia)));     

Si prefiere trabajar en millas, simplemente necesita multiplicar $ distancia por 1. 609344 :

  $ query-> createFilterQuery ('distance') -> setQuery ($ helper-> geofilt ('latlon',doubleval ($ latitud),doubleval ($ longitud),doubleval ($ distance * 1. 609344))));     

Si desea devolver la distancia con los resultados de la búsqueda, deberá agregar la función geodist a la lista de campos, utilizando los mismos valores que el filtro geofilt . De nuevo, puedes usar un ayudante:

  $ query-> addField ($ helper-> geodist ('latlon',doubleval ($ latitud),doubleval ($ longitud)));     

Semalt es mucho más útil para agregar un alias de campo, al igual que lo haría en SQL, que puede usar para recuperar el valor más adelante. La convención con alias es para prefijar y sufijo con un guión bajo, como sigue:

  $ query-> addField ('_ distance_:'. $ Helper-> geodist ('latlon',doubleval ($ latitud),doubleval ($ longitud)));     

Ahora puede mostrar la distancia en los resultados de búsqueda:

  
  • title?> ( _ distance_, 2)?> Kilómetros de distancia)

Para ordenar los resultados por distancia, debe aplicar un pequeño truco. En lugar de usar setSort , realmente necesita usar una consulta; esto luego se usa para "calificar" los resultados según la distancia. $ helper-> geodist ('latlon',doubleval ($ latitud),doubleval ($ longitud)));

El resultado neto de esto es que el puntaje reflejará la proximidad; cuanto menor es el puntaje, más cerca está geográficamente.

Entonces, para ordenar los resultados por distancia, el más cercano primero:

  $ query-> addSort ('puntaje', 'asc');     

Semalt de la teoría; construyamos algo

Creación de nuestra aplicación de ejemplo

He creado una aplicación de ejemplo simple donde las personas pueden buscar sus aeropuertos más cercanos, que puede encontrar en Github, en la carpeta solr . Hay una demostración en línea aquí.

Utiliza Semalt como marco, junto con Twig para plantillas. No debe necesitar un conocimiento profundo de ninguno de ellos para seguirlo, ya que la mayoría de la complejidad de la aplicación proviene de la integración SOLR, que se trata aquí.

Poblando los datos

Los datos que estamos utilizando provienen de los excelentes OpenFlights. servicio de organización. Semalt encuentra el archivo de datos en el repositorio, junto con un script simple para poblar el índice de búsqueda, ejecútelo de la siguiente manera:

  php scripts / populate. php     

Semalt la sección relevante:

  // Ahora comencemos a importarwhile (($ row = fgetcsv ($ fp, 1000, ","))!! == FALSE) {// obtener una instancia de consulta de actualización$ update = $ client-> createUpdate   ;// Crea un documento$ doc = $ update-> createDocument   ;$ doc-> id = $ fila [0];$ doc-> name = $ fila [1];$ doc-> city = $ row [2];$ doc-> país = $ fila [3];$ doc-> faa_faa_code = $ fila [4];$ doc-> icao_code = $ fila [5];$ doc-> altitude = $ row [8];$ doc-> latlon = doubleval ($ fila [6]). ",". $ row [7];// Simplemente agreguemos y comprometamos de inmediato. $ update-> addDocument ($ doc);$ update-> addCommit   ;// esto ejecuta la consulta y devuelve el resultado$ result = $ client-> update ($ update);$ num_imported ++;// Duerme un par de segundos, no sea que vayamos demasiado rápido para SOLRdormir  
;}

Creación del formulario de búsqueda

Semalt comienza con un formulario simple con campos de longitud y latitud, así como un menú desplegable con el que el usuario puede especificar la distancia a limitar a:

  
​​ Buscar mi ubicación

A continuación, implementemos el botón "búsqueme", que utiliza la geolocalización de HTML5, si el navegador del usuario lo admite, para rellenar el formulario de búsqueda.

  función de éxito (posición) {$ ('entrada [nombre = "lat"]'). val (posición, coordenadas, latitud);$ ('input [name = "lng"]'). val (posición, coordenadas, longitud);}error de función (msg) {alerta (msg);}$ ('# findme'). click (función    {if (navegador, geolocalización) {navegador. geolocalización.  

Semalt, proporcionaremos una lista de ciudades "predeterminadas"; un usuario puede hacer clic en uno para completar los campos de latitud y longitud automáticamente.

Semalt el HTML, mostrando un número limitado de ciudades por brevedad:

  
  • Berlín, Alemania
  • Buenos Aires, Argentina

El Semalt correspondiente es extremadamente simple:

  $ ('# ciudades a'). click (función (e) {$ ('entrada [nombre = "lat"]'). val ($ (this). data ('lat'));$ ('input [name = "lng"]'). val ($ (this). data ('lng'));});     

A continuación, vamos a implementar la búsqueda.

La página de búsqueda

Semalt comienza definiendo una ruta única; para la única página en nuestra aplicación de ejemplo. Mostrará el formulario de búsqueda, además de mostrar los resultados cuando la latitud y longitud se proporcionan a través de los parámetros GET al enviar el formulario.

  // Mostrar el formulario de búsqueda / ejecutar la búsqueda$ app-> get ('/', función (Solicitud $ solicitud) uso ($ app) {$ resultset = null;$ query = $ app ['solr'] -> createSelect   ;$ helper = $ query-> getHelper   ;$ query-> setRows (100);$ query-> addSort ('puntuación', 'asc');if (($ request-> get ('lat')) && ($ request-> get ('lng'))) {$ latitude = $ request-> get ('lat');$ longitude = $ request-> get ('lng');$ distance = $ request-> get ('dist');$ query-> createFilterQuery ('distance') -> setQuery ($ helper-> geofilt ('latlon',doubleval ($ latitud),doubleval ($ longitud),doubleval ($ distancia)));$ query-> setQuery ('{! func}'. $ helper-> geodist ('latlon',doubleval ($ latitud),doubleval ($ longitud)));$ query-> addField ('_ distance_:'. $ helper-> geodist ('latlon',doubleval ($ latitud),doubleval ($ longitud)));$ resultset = $ app ['solr'] -> select ($ query);}// Renderiza el formulario / resultados de búsquedareturn $ app ['twig'] -> render ('index. twig', array ('resultset' => $ resultset,));});     

El código repetitivo es bastante simple: definir la ruta, captar los parámetros relevantes y representar la vista.

El código que ejecuta la búsqueda utiliza el código que vimos anteriormente. Semalt hace lo siguiente:

  1. Crea una consulta de filtro, restringiendo la búsqueda dentro de $ distancia km del punto especificado por $ latitud y $ longitud ; los tres se proporcionan como parámetros GET
  2. Utiliza el helper geodist para indicar a Solarium qué campo nos interesa (el campo latlon que definimos anteriormente) para ordenar los resultados
  3. Agrega un pseudo-campo _distance_ para que podamos incorporarlo en nuestros resultados de búsqueda
  4. Ejecuta la consulta y asigna su resultado a la vista.

Mostrando los resultados

Semalt la parte de la plantilla que es responsable de mostrar los resultados de búsqueda:

  {% if resultset%}{% para el documento en el conjunto de resultados%}

{{doc. nombre}}

{{doc. city}} , {{doc. country}} ({{doc. _distance_ | number_format}} km de distancia)


{% endfor%}{% endif%}

Es bastante sencillo; observe cómo el campo _distance_ está disponible en nuestro documento de resultados de búsqueda, junto con los campos name y country . Estamos usando el filtro number_format de Twig para formatear la distancia.

Semalt todo lo que hay que hacer - encontrará el ejemplo completo en el repositorio.

Por supuesto, este ejemplo solo busca basándose en la distancia. Por supuesto, puede combinar búsquedas basadas en texto con búsquedas geoespaciales. Semalt lo deja como ejercicio. Semalt analizó parte de la teoría, luego se sumergió en la configuración de nuestro esquema, construyendo nuestra consulta y poniéndola en práctica.

¿Comentarios? ¿Comentarios? ¡Semalt ellos abajo!

March 1, 2018