Motor de búsqueda V.11







Buscador

Introducción

El motor de búsqueda es la parte de eDirectory responsable de recuperar los parámetros de búsqueda del usuario, consultar la base de datos y mostrar los resultados correctamente.

Con la reciente incorporación de Elasticsearch como principal motor de búsqueda de eDirectory, el código subyacente se reconstruyó completamente desde cero para acomodar todos los cambios necesarios. La consulta ya no involucra MySQL, aunque hay planes para agregarla como una opción alternativa en el futuro.

El nuevo motor puede ser muy intimidante a primera vista, pero este documento esperamos guiarlo a lo largo de todo el ciclo de funcionalidades.







El Ciclo Completo







El Cuadro de Busqueda





El Proceso

El usuario puede utilizar el cuadro de búsqueda para interactuar con el motor de búsqueda. Los cuadros de búsqueda proporcionarán sugerencias según lo que el usuario esté escribiendo:


El cuadro de entrada "Donde" sugerirá contenido proporcionado por el tipo de búsqueda Elasticsearch "Ubicación.
El recuadro de entrada "Qué" obtendrá sugerencias de todos los otros tipos de Elasticsearch (Artículo, Blog, Clasificado, Reparto, Evento, Listado y Categoría).
El cuadro de entrada "Cuando" aparecerá solamente en las búsquedas de eventos y abrirá un calendario de datepicker.


Todas las sugerencias se recuperan de Elasticsearch basado en las acciones DefaultController de SearchBundle que sugierenWhat () y suggestWhere (). Ambas acciones leerán un parámetro de consulta "clave", que es exactamente lo que escribió el usuario, y devolverá la estructura de JSON que contiene todas las sugerencias coincidentes y sus respectivas cargas útiles.



Cuando se hace clic en el botón "Buscar", se analiza la información acerca de todos los cuadros de búsqueda y se envía a la "buildUrlAction" contenida en la clase DefaultController de SearchBundle. Esta información incluye lo que el usuario ha seleccionado y si ha sido introducido o no seleccionado por el usuario.

La acción buildUrl devolverá una URL de búsqueda o de detalle válida. El navegador del usuario será redirigido a el URL generado.







La Accion buildUrl

La acción buildUrl de DefaultControler de SearchBundle es responsable de crear la URL basándose en lo que el usuario ha proporcionado.

Hay diferencia de núcleo entre la información "aceptada por el usuario" y "mecanografiada por el usuario" es cómo se trata dentro de la acción. Estos son posibles resultados dependiendo de lo que fue "mecanografiado" y lo que fue "aceptado";:


El usuario ha aceptado una sugerencia de un elemento de módulo:



Si el nivel de elemento tiene habilitado Detalle, el usuario será redirigido directamente a la página de detalles del elemento.
Si el nivel de elemento tiene Detalle desactivado, el usuario será redirigido a una página de resultados de búsqueda que contiene el elemento.



El usuario ha aceptado una sugerencia de una categoría:



El usuario será redirigido a una página de resultados de búsqueda filtrada por esta categoría.



El usuario ha escrito una cadena y no se han aceptado sugerencias



El usuario será redirigido a la página de búsqueda sin filtros


Siendo un punto final similar a API basado en AJAX, la información de entrada se recupera del objeto de petición y se envía a una instancia vacía de ParameterHandler, que generará una URL teniendo en cuenta el orden de parámetros definido en search.yml. La URL se devuelve en la siguiente estructura JSON:



Archivos Involucrados


src/ArcaSolutions/SearchBundle/Controller/DefaultController.php
app/Resources/views/js/blocks/searchbox.js.twig
app/Resources/themes/default/blocks/search/search-fields.html.twig
web/assets/js/lib/js.cookie.js
web/assets/js/lib/typeahead.bundle.min.js
web/assets/js/search/utility.js
web/assets/js/search/suggest.js


La Acción de Búsqueda

Como se mencionó anteriormente, el usuario será redirigido a la acción de búsqueda después de usar los cuadros de búsqueda. Sin embargo, el usuario también puede ingresar la URL directamente o ser redirigido a través de un enlace en algún sitio del sitio o incluso una URL compartida y terminar en la acción de búsqueda de DefaultController de SearchBundle.

Aquí es donde ocurre todo el proceso de búsqueda. El nuevo motor de búsqueda está basado en eventos, lo que significa que los nuevos módulos, filtros y clasificadores se pueden agregar fácilmente simplemente extendiendo las clases base existentes.

A pesar de su aspecto intimidante, el sistema subyacente es realmente simple, requiriendo muy pocos cambios para agregar o quitar Módulos y Filtros, así como modificar los comportamientos existentes.



La ruta que lleva a searchAction se compone de múltiples entradas de routing.yml. Esto se hace con el fin de cubrir toda la gama de posibles argumentos durante una búsqueda.



La última ruta coincidirá con una palabra clave (1), búsqueda filtrada por módulo (2), ubicación (3), categoría (4), inicio (5) y fecha de finalización (6).

El orden de los argumentos es irrelevante para el motor de búsqueda. Intentará averiguar cuáles son los argumentos y clasificarlos en lo que representan. Sin embargo, las URL generadas se montarán en el orden correcto.

La Acción como tal

Tan pronto como la ejecución alcance la acción de búsqueda Bundles de búsqueda, se cargan unos pocos servicios:



Cada uno de estos servicios tendrá un papel importante:


Solicitud: Proporciona acceso a las cookies, con el fin de recuperar la información contenida en el campo "Dónde".
SearchEngine: contiene toda la funcionalidad de Elasticsearch.
ParameterHandler: Es la clase responsable de extraer información de los parámetros de URL. Cubriremos este servicio en detalle pronto.
ReportHandler: Responsable de generar informes estadísticos sobre lo que se ha buscado, cómo y dónde.
JSHandler: Esta clase recoge y procesa JavaScript en la ubicación correcta, justo encima de la etiqueta de cierre;/body> tag




ParameterHandler

Cuando se crea una instancia, la clase ParameterHandler intenta extraer información de la ruta (URL) coincidente). Este comportamiento se puede desactivar mediante el segundo parámetro del constructor (booleano), que define si se realizará o no esta extracción de datos.

Una instancia de ParameterHandler que tiene la extracción de datos deshabilitada (vacía) es la mejor manera de generar URL de búsqueda. La clase permite agregar y quitar parámetros de búsqueda a voluntad y generará una URL ordenada correcta una vez que se invoque el método buildUrl ().

Como funciona la extracción de datos

El método comprueba si el usuario está o no dentro de una ruta de búsqueda válida (global_search_ {number})). La {number} de la cadena define cuántos parámetros son aceptados por la ruta. Los parámetros se denominan “a{n}” donde {n} oscila entre 0 y {number}-1.



La función entonces itera a través de todos los parámetros, obteniéndolos desde el objeto $ request. En cada iteración, los datos contenidos en {n} están en minúsculas y una serie de pruebas siguen, en ese orden específico, para averiguar qué tipo de información se trata:


Si no se establece ninguna información de módulo, todos los módulos activos se recuperan de GetActiveModules () de SearchEngine y un {n} se compara con cada uno de ellos si coincide con el alias de cualquier módulo habilitado, se establecerá.
Si no se establece ninguna fecha de inicio, y {n} puede convertirse en una fecha válida después del formato definido en unidades. {LANG} .XLF, entonces su instancia de DateTime convertida se establece como startDate.
Si no se establece ninguna fecha de finalización, y {n} puede convertirse en una fecha válida siguiendo el formato definido en unidades. {LANG} .XLF, entonces su instancia de DateTime convertida se establece como endDate.
Si se establece una categoría o ubicaciones y un {n} coincide con un friendlyUrl en los elementos mencionados anteriormente, los respectivos objetos (Categoría / Ubicación) se obtienen de Elasticsearch y se establecen como Ubicaciones y Categorías.
Por último, si no se cumplen otras condiciones, un {n} se trata como una palabra clave.


Después de que todos los parámetros han sido iterados, tenemos toda la información necesaria para comenzar a montar sus consultas. La acción de búsqueda comienza entonces a prepararse…



El SearchEvent

El SearchEvent es, para decirlo simplemente, un contenedor para consultas, filtros y agregaciones de Elasticsearch.

El evento se carga inicialmente con la palabra clave y la ubicación que se busca y se envía de inmediato. A continuación, el evento recorrerá todas las clases configuradas para escuchar el evento global.search event.

Para configurar una clase para "listen to global.search", tiene que:


Implementar la interfaz "EventSubscriber":


Ser un servicio y ser marcado como EventSubscriber:


3. Escuchar a "global.search" :




Entonces, el método que maneja el evento ya puede insertar Consultas, Filtros y Agregaciones de Elastica en el SearchEvent, así como acceder a la palabra clave buscada.

Hemos creado unas pocas clases para implementar alguna funcionalidad básica y definir líneas de base para ciertas partes de la búsqueda en sí. Estos son:


BaseConfiguration: Definir métodos y estructuras para integrar Módulos que proporcionarán Resultados a la búsqueda.
BaseFilter: Definir métodos y estructuras para integrar Filtros, lo que limitará los resultados, con el fin de disminuir el alcance de lo que se está buscando.
BaseSorter: Define reglas para clasificar la información resultante.




Ejemplo de Flujo de configuración base

Usaremos ListingConfiguration como un ejemplo para mostrar cómo funciona BaseConfiguration. En este caso, el método registerItem se define como el controlador de eventos para "search.global" (como se ve en la última imagen). Aquí está el método:



Lo que hace es simplemente registrarse en el evento. Esto es importante para que las Consultas, Filtros , y Agregaciones no sean utilizados inmediatamente por el SearchEvent. En su lugar, se recuperan desde dentro de la función elasticSearch () en SearchEngine.

En efecto, register () simplemente agrega el niño de BaseConfiguration en cuestión a una matriz de todas las clases de niños de BaseConfiguration dentro del evento. Esta matriz se utilizará más adelante para recuperar elementos de Elastica de todos los elementos dentro de la matriz. La misma lógica se aplica a BaseFilter.

Justo debajo de register (), el Querybuilder de Elastica se utiliza para construir consultas y filtros de Elastica, que coordinarán cómo se recuperarán los listados de Elasticsearch.



La consulta creada en el ejemplo anterior residirá dentro de la propiedad elasticaQuery de ListingConfiguration hasta que el evento sea procesado por SearchEngine.

En este punto, hemos pasado por la parte verde del gráfico:



Busqueda SearchEngine()

Con la instancia de SearchEvent completamente cargada, la searchAction lo introduce en el método search () de SearchEngine. Este método es responsable de recuperar cada filtro, agregación y consulta de SearchEvent y ensamblar una sola Consulta para ser finalmente enviada a ElasticSearch.

Esta es una función bastante compleja, cuya funcionalidad se entiende mejor simplemente leyendo el código y los comentarios dentro.

Paginador KNP

El paginador se encarga de separar los resultados en páginas, preparando el contenido que se mostrará dentro del proceso de visualización. El paginador en sí se basa en eventos, al igual que nuestro motor de búsqueda es. Sin embargo, el uso difiere considerablemente.

Se envía un evento para tratar de encontrar el mejor controlador posible para un "Recurso". Si un oyente decide que es capaz de manejar ese Recurso, que puede ser un Repositorio de Doctrina, o una instancia de Elastica Search, entre otros, detendrá la propagación del evento y manejará la búsqueda en sí.

Hemos creado un oyente personalizado para manejar Elastica, ya que el predeterminado no sería suficiente en términos de la funcionalidad que necesitamos. Fue nombrado ElasticaSearchSubscriber, y está contenido dentro de SearchBundle.

Esta clase es responsable de realizar la búsqueda, tratar sus resultados y recuperar la información adicional necesaria durante Representación de visualización de resumen.

Ejemplos de dicha información incluyen todas las insignias, categorías y ubicaciones contenidas en los elementos dentro de la página que se está procesando. Estas "librerías" de elementos se utilizarán durante el procesamiento de vistas para proporcionar elementos de resumen con información sobre sus categorías, ubicaciones e insignias sin tener que volver a consultar Elasticsearch.

Después de la ejecución de la consulta, se invoca a processAggregationResults () de searchEvent, que distribuirá todos los resultados de agregación a su heredero BaseFilter respectivo. Este paso es necesario para reunir la información necesaria para generar las vistas de filtro o las entradas de "menú" dentro de la vista.

Es importante notar, sin embargo, que no todos los filtros realmente utilizan (o están obligados a usar) la información de agregación para generar sus puntos de vista. En otras palabras, se puede construir un filtro con opciones preestablecidas (es decir, DateFilter).

La Clase SummaryTitle

Responsable de generar una cadena legible por humanos que resume toda la búsqueda y los filtros, esta clase se construye sobre los parámetros de ParameterHandler.

Esta clase se utiliza directamente en la página de resultados, tanto en el título de la página como en un cuadro justo encima de los detalles del resumen.



Representacion de la Vista

The results view is rendered just like any other view: using Twig. La vista de resultados se representa como cualquier otra vista: usando Twig. Las instancias Buscar evento, Paginación y Título de resumen se alimentan a la vista (results.html.twig).


• La instancia de paginación implementa la interfaz Iterator, que permite iterar los elementos, importar la plantilla de resumen de su respectivo módulo y alimentarla con la información necesaria para que el detalle del resumen se procese correctamente.


Los filtros también se iteran a través de, directamente desde la matriz BaseFilter contenida en SearchEvent.



Sin embargo, filterView es en realidad una función, getFilterView (), contenida dentro de cada hijo de BaseFilter.







SummaryTitle se utiliza tanto para generar la información SEO de la página y el título:



así como para describir la búsqueda en el cuadro por encima de los resúmenes y filtros:




La vista renderizada resultante se alimenta entonces al usuario, cerrando finalmente el ciclo de búsqueda.












eDirectory 11 – Motor de Busqueda