1. Paquetes
  2. Laravel Scout

Introducción

Laravel Scout proporciona una solución simple y basada en controladores para agregar búsqueda de texto completo a tus modelos Eloquent. Utilizando observadores de modelo, Scout mantendrá automáticamente sincronizados tus índices de búsqueda con tus registros Eloquent.

Actualmente, Scout se suministra con controladores Algolia, Meilisearch y MySQL / PostgreSQL (database). Además, Scout incluye un controlador "collection" diseñado para el uso en desarrollo local y que no requiere dependencias externas ni servicios de terceros. Además, escribir controladores personalizados es simple y puedes extender Scout con tus propias implementaciones de búsqueda.

Instalación

Primero, instala Scout a través del gestor de paquetes Composer:

composer require laravel/scout

Después de instalar Scout, debes publicar el archivo de configuración de Scout usando el comando Artisan vendor:publish. Este comando publicará el archivo de configuración scout.php en el directorio config de tu aplicación:

php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"

Finalmente, agrega el rasgo Laravel\Scout\Searchable al modelo que deseas hacer buscable. Este rasgo registrará un observador de modelo que mantendrá automáticamente el modelo sincronizado con tu controlador de búsqueda:

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
 
class Post extends Model
{
use Searchable;
}

Prerrequisitos del Controlador

Algolia

Cuando uses el controlador de Algolia, debes configurar tus credenciales de Algolia id y secret en tu archivo de configuración config/scout.php. Una vez configuradas tus credenciales, también deberás instalar el SDK de PHP de Algolia a través del gestor de paquetes Composer:

composer require algolia/algoliasearch-client-php

Meilisearch

Meilisearch es un motor de búsqueda de código abierto y extremadamente rápido. Si no estás seguro de cómo instalar Meilisearch en tu máquina local, puedes usar Laravel Sail, el entorno de desarrollo Docker oficialmente admitido por Laravel.

Cuando uses el controlador de Meilisearch, deberás instalar el SDK de PHP de Meilisearch a través del gestor de paquetes Composer:

composer require meilisearch/meilisearch-php http-interop/http-factory-guzzle

Luego, establece la variable de entorno SCOUT_DRIVER así como tus credenciales host y key de Meilisearch en el archivo .env de tu aplicación:

SCOUT_DRIVER=meilisearch
MEILISEARCH_HOST=http://127.0.0.1:7700
MEILISEARCH_KEY=masterKey

Para obtener más información sobre Meilisearch, consulta la documentación de Meilisearch.

Además, asegúrate de instalar una versión de meilisearch/meilisearch-php que sea compatible con tu versión binaria de Meilisearch revisando la documentación de Meilisearch sobre compatibilidad binaria.

Advertencia Cuando actualices Scout en una aplicación que utiliza Meilisearch, siempre debes revisar cualquier cambio adicional que pueda causar problemas en el servicio Meilisearch en sí.

Encolamiento

Aunque no es estrictamente necesario utilizar Scout, deberías considerar configurar un controlador de cola antes de usar la biblioteca. Ejecutar un trabajador de cola permitirá que Scout encole todas las operaciones que sincronizan la información de tu modelo con tus índices de búsqueda, proporcionando tiempos de respuesta mucho mejores para la interfaz web de tu aplicación.

Una vez que hayas configurado un controlador de cola, establece el valor de la opción queue en tu archivo de configuración config/scout.php en true:

'queue' => true,

Incluso cuando la opción queue se establece en false, es importante recordar que algunos controladores de Scout como Algolia y Meilisearch siempre indexan registros de forma asíncrona. Esto significa que, aunque la operación de índice se haya completado dentro de tu aplicación Laravel, el motor de búsqueda en sí puede no reflejar de inmediato los registros nuevos y actualizados.

Para especificar la conexión y cola que utilizan tus trabajos Scout, puedes definir la opción de configuración queue como un array:

'queue' => [
'connection' => 'redis',
'queue' => 'scout'
],

Configuración

Configuración de Índices del Modelo

Cada modelo Eloquent se sincroniza con un "índice" de búsqueda dado, que contiene todos los registros buscables para ese modelo. En otras palabras, puedes pensar en cada índice como una tabla MySQL. Por defecto, cada modelo se persistirá en un índice que coincide con el nombre "habitual" de la "tabla" del modelo. Normalmente, este es la forma en plural del nombre del modelo; sin embargo, eres libre de personalizar el índice del modelo sobrescribiendo el método searchableAs en el modelo:

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
 
class Post extends Model
{
use Searchable;
 
/**
* Obtén el nombre del índice asociado al modelo.
*/
public function searchableAs(): string
{
return 'posts_index';
}
}

Configuración de Datos Buscables

Por defecto, toda la forma toArray de un modelo dado se persistirá en su índice de búsqueda. Si deseas personalizar los datos que se sincronizan con el índice de búsqueda, puedes sobrescribir el método toSearchableArray en el modelo:

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
 
class Post extends Model
{
use Searchable;
 
/**
* Obtén el array de datos indexables para el modelo.
*
* @return array<string, mixed>
*/
public function toSearchableArray(): array
{
$array = $this->toArray();
 
// Personaliza el array de datos...
 
return $array;
}
}

Algunos motores de búsqueda como Meilisearch solo realizarán operaciones de filtro (>, <, etc.) en datos del tipo correcto. Entonces, al usar estos motores de búsqueda y personalizar tus datos buscables, debes asegurarte de que los valores numéricos se conviertan a su tipo correcto:

public function toSearchableArray()
{
return [
'id' => (int) $this->id,
'name' => $this->name,
'price' => (float) $this->price,
];
}

Configuración de Datos Filtrables y Ajustes de Índices (Meilisearch)

A diferencia de otros controladores de Scout, Meilisearch requiere que predefinas la configuración de búsqueda del índice, como atributos filtrables, atributos ordenables y otros campos de configuración admitidos.

Los atributos filtrables son aquellos atributos que planeas filtrar al invocar el método where de Scout, mientras que los atributos ordenables son aquellos que planeas ordenar al invocar el método orderBy de Scout. Para definir la configuración de tu índice, ajusta la parte index-settings de tu entrada de configuración meilisearch en el archivo de configuración scout de tu aplicación:

use App\Models\User;
use App\Models\Flight;
 
'meilisearch' => [
'host' => env('MEILISEARCH_HOST', 'http://localhost:7700'),
'key' => env('MEILISEARCH_KEY', null),
'index-settings' => [
User::class => [
'filterableAttributes'=> ['id', 'name', 'email'],
'sortableAttributes' => ['created_at'],
// Otros campos de configuración...
],
Flight::class => [
'filterableAttributes'=> ['id', 'destination'],
'sortableAttributes' => ['updated_at'],
],
],
],

Si el modelo subyacente a un índice dado se puede eliminar suavemente y está incluido en el array index-settings, Scout incluirá automáticamente el soporte para filtrar en modelos eliminados suavemente en ese índice. Si no tienes otros atributos filtrables u ordenables que definir para un índice de modelo eliminable suavemente, simplemente agrega una entrada vacía al array index-settings para ese modelo:

'index-settings' => [
Flight::class => []
],

Después de configurar la configuración de índice de tu aplicación, debes invocar el comando Artisan scout:sync-index-settings. Este comando informará a Meilisearch de tu configuración actual de índice. Para mayor comodidad, es posible que desees incluir este comando como parte de tu proceso de implementación:

php artisan scout:sync-index-settings

Configuración del ID del Modelo

Por defecto, Scout utilizará la clave primaria del modelo como el ID/clave único del modelo que se almacena en el índice de búsqueda. Si necesitas personalizar este comportamiento, puedes sobrescribir los métodos getScoutKey y getScoutKeyName en el modelo:

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
 
class User extends Model
{
use Searchable;
 
/**
* Obtén el valor utilizado para indexar el modelo.
*/
public function getScoutKey(): mixed
{
return $this->email;
}
 
/**
* Obtén el nombre clave utilizado para indexar el modelo.
*/
public function getScoutKeyName(): mixed
{
return 'email';
}
}

Configuración de Motores de Búsqueda por Modelo

Al realizar búsquedas, Scout utilizará típicamente el motor de búsqueda predeterminado especificado en el archivo de configuración scout de tu aplicación. Sin embargo, el motor de búsqueda para un modelo en particular se puede cambiar sobrescribiendo el método searchableUsing en el modelo:

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Engines\Engine;
use Laravel\Scout\EngineManager;
use Laravel\Scout\Searchable;
 
class User extends Model
{
use Searchable;
 
/**
* Obtén el motor utilizado para indexar el modelo.
*/
public function searchableUsing(): Engine
{
return app(EngineManager::class)->engine('meilisearch');
}
}

Identificación de Usuarios

Scout también te permite identificar automáticamente a los usuarios al usar Algolia. Asociar al usuario autenticado con las operaciones de búsqueda puede ser útil al ver tus análisis de búsqueda dentro del panel de Algolia. Puedes habilitar la identificación del usuario definiendo una variable de entorno SCOUT_IDENTIFY como true en el archivo .env de tu aplicación:

SCOUT_IDENTIFY=true

Habilitar esta función también pasará la dirección IP de la solicitud y el identificador principal de tu usuario autenticado a Algolia para que estos datos estén asociados con cualquier solicitud de búsqueda realizada por el usuario.

Motores de Base de Datos / Colección

Motor de Base de Datos

Advertencia El motor de base de datos actualmente admite MySQL y PostgreSQL.

Si tu aplicación interactúa con bases de datos pequeñas o medianas o tiene una carga de trabajo ligera, es posible que encuentres más conveniente comenzar con el motor "database" de Scout. El motor de base de datos utilizará cláusulas "where like" e índices de texto completo al filtrar resultados de tu base de datos existente para determinar los resultados de búsqueda aplicables para tu consulta.

Para usar el motor de base de datos, simplemente establece el valor de la variable de entorno SCOUT_DRIVER en database, o especifica el controlador database directamente en el archivo de configuración scout de tu aplicación:

SCOUT_DRIVER=database

Una vez que hayas especificado el motor de base de datos como tu controlador preferido, debes configurar tus datos buscables. Luego, puedes comenzar a realizar consultas de búsqueda contra tus modelos. No es necesario realizar indexación de motores de búsqueda, como la indexación necesaria para sembrar índices de Algolia o Meilisearch, al utilizar el motor de base de datos.

Personalización de Estrategias de Búsqueda en la Base de Datos

Por defecto, el motor de base de datos ejecutará una consulta "where like" contra cada atributo del modelo que hayas configurado como buscable. Sin embargo, en algunas situaciones, esto puede resultar en un rendimiento deficiente. Por lo tanto, la estrategia de búsqueda del motor de base de datos se puede configurar para que algunas columnas especificadas utilicen consultas de búsqueda de texto completo o solo utilicen restricciones "where like" para buscar los prefijos de las cadenas (ejemplo%) en lugar de buscar dentro de toda la cadena (%ejemplo%).

Para definir este comportamiento, puedes asignar atributos PHP al método toSearchableArray de tu modelo. Cualquier columna que no se le asignen comportamientos adicionales de estrategia de búsqueda continuará utilizando la estrategia predeterminada "where like":

use Laravel\Scout\Attributes\SearchUsingFullText;
use Laravel\Scout\Attributes\SearchUsingPrefix;
 
/**
* Obtén el array de datos indexables para el modelo.
*
* @return array<string, mixed>
*/
#[SearchUsingPrefix(['id', 'email'])]
#[SearchUsingFullText(['bio'])]
public function toSearchableArray(): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'bio' => $this->bio,
];
}

Advertencia Antes de especificar que una columna debe usar restricciones de consulta de texto completo, asegúrate de que la columna haya sido asignada a un índice de texto completo.

Motor de Colección

Aunque puedes utilizar los motores de búsqueda Algolia o Meilisearch durante el desarrollo local, es posible que encuentres más conveniente comenzar con el motor "collection". El motor de colección utilizará cláusulas "where" y filtrado de colecciones en los resultados de tu base de datos existente para determinar los resultados de búsqueda aplicables para tu consulta. Cuando uses este motor, no será necesario "indexar" tus modelos buscables, ya que simplemente se recuperarán de tu base de datos local.

Para usar el motor de colección, simplemente establece el valor de la variable de entorno SCOUT_DRIVER en collection, o especifica el controlador collection directamente en el archivo de configuración scout de tu aplicación:

SCOUT_DRIVER=collection

Una vez que hayas especificado el controlador de colección como tu controlador preferido, puedes comenzar a realizar consultas de búsqueda contra tus modelos. La indexación del motor de búsqueda, como la necesaria para sembrar los índices de Algolia o Meilisearch, no es necesaria al usar el motor de colección.

Diferencias con el Motor de Base de Datos

A primera vista, los motores "database" y "collections" son bastante similares. Ambos interactúan directamente con tu base de datos para recuperar resultados de búsqueda. Sin embargo, el motor de colección no utiliza índices de texto completo o cláusulas LIKE para encontrar registros coincidentes. En su lugar, extrae todos los registros posibles y utiliza el ayudante Str::is de Laravel para determinar si la cadena de búsqueda existe dentro de los valores de atributo del modelo.

El motor de colección es el motor de búsqueda más portable, ya que funciona en todas las bases de datos relacionales admitidas por Laravel (incluyendo SQLite y SQL Server); sin embargo, es menos eficiente que el motor de base de datos de Scout.

Indexación

Importación por Lotes

Si estás instalando Scout en un proyecto existente, es posible que ya tengas registros de base de datos que necesitas importar a tus índices. Scout proporciona un comando Artisan scout:import que puedes usar para importar todos tus registros existentes a tus índices de búsqueda:

php artisan scout:import "App\Models\Post"

El comando flush se puede usar para eliminar todos los registros de un modelo de tus índices de búsqueda:

php artisan scout:flush "App\Models\Post"

Modificación de la Consulta de Importación

Si deseas modificar la consulta que se utiliza para recuperar todos tus modelos para la importación por lotes, puedes definir un método makeAllSearchableUsing en tu modelo. Este es un buen lugar para agregar cualquier carga de relación ansiosa que pueda ser necesaria antes de importar tus modelos:

use Illuminate\Database\Eloquent\Builder;
 
/**
* Modifica la consulta utilizada para recuperar modelos al hacer que todos los modelos sean buscables.
*/
protected function makeAllSearchableUsing(Builder $query): Builder
{
return $query->with('author');
}

Advertencia El método makeAllSearchableUsing puede no ser aplicable al usar una cola para importar por lotes modelos. Las relaciones no se restauran cuando las colecciones de modelos son procesadas por trabajos.

Agregar Registros

Una vez que hayas agregado el rasgo Laravel\Scout\Searchable a un modelo, todo lo que necesitas hacer es guardar o crear una instancia del modelo y se agregará automáticamente a tu índice de búsqueda. Si has configurado Scout para usar colas, esta operación se realizará en segundo plano por tu trabajador de cola:

use App\Models\Order;
 
$order = new Order;
 
// ...
 
$order->save();

Agregar Registros Via Consulta

Si deseas agregar una colección de modelos a tu índice de búsqueda a través de una consulta Eloquent, puedes encadenar el método searchable a la consulta Eloquent. El método searchable fragmentará los resultados de la consulta y agregará los registros a tu índice de búsqueda. Nuevamente, si has configurado Scout para usar colas, todos los fragmentos se importarán en segundo plano por tus trabajadores de cola:

use App\Models\Order;
 
Order::where('price', '>', 100)->searchable();

También puedes llamar al método searchable en una instancia de relación Eloquent:

$user->orders()->searchable();

O, si ya tienes una colección de modelos Eloquent en memoria, puedes llamar al método searchable en la instancia de colección para agregar las instancias del modelo a su índice correspondiente:

$orders->searchable();

Nota El método searchable se puede considerar una operación "upsert". En otras palabras, si el registro del modelo ya está en tu índice, se actualizará. Si no existe en el índice de búsqueda, se agregará al índice.

Actualizar Registros

Para actualizar un modelo buscable, solo necesitas actualizar las propiedades de la instancia del modelo y guardar el modelo en tu base de datos. Scout automáticamente persistirá los cambios en tu índice de búsqueda:

use App\Models\Order;
 
$order = Order::find(1);
 
// Actualiza el orden...
 
$order->save();

También puedes invocar el método searchable en una instancia de consulta Eloquent para actualizar una colección de modelos. Si los modelos no existen en tu índice de búsqueda, se crearán:

Order::where('price', '>', 100)->searchable();

Si deseas actualizar los registros del índice de búsqueda para todos los modelos en una relación, puedes invocar el método searchable en la instancia de relación:

$user->orders()->searchable();

O, si ya tienes una colección de modelos Eloquent en memoria, puedes llamar al método searchable en la instancia de colección para actualizar las instancias del modelo en su índice correspondiente:

$orders->searchable();

Modificación de Registros Antes de la Importación

A veces, es posible que necesites preparar la colección de modelos antes de hacerlos buscables. Por ejemplo, es posible que desees cargar ansiosamente una relación para que los datos de la relación se puedan agregar eficientemente a tu índice de búsqueda. Para lograr esto, define un método makeSearchableUsing en el modelo correspondiente:

use Illuminate\Database\Eloquent\Collection;
 
/**
* Modifica la colección de modelos que se están volviendo buscables.
*/
public function makeSearchableUsing(Collection $models): Collection
{
return $models->load('author');
}

Eliminar Registros

Para eliminar un registro de tu índice, simplemente puedes eliminar el modelo de la base de datos. Esto se puede hacer incluso si estás utilizando modelos eliminados suavemente:

use App\Models\Order;
 
$order = Order::find(1);
 
$order->delete();

Si no deseas recuperar el modelo antes de eliminar el registro, puedes usar el método unsearchable en una instancia de consulta Eloquent:

Order::where('price', '>', 100)->unsearchable();

Si deseas eliminar los registros del índice de búsqueda para todos los modelos en una relación, puedes invocar el método unsearchable en la instancia de relación:

$user->orders()->unsearchable();

O, si ya tienes una colección de modelos Eloquent en memoria, puedes llamar al método unsearchable en la instancia de colección para eliminar las instancias del modelo de su índice correspondiente:

$orders->unsearchable();

Pausar Indexación

A veces, es posible que necesites realizar un lote de operaciones Eloquent en un modelo sin sincronizar los datos del modelo con tu índice de búsqueda. Puedes hacer esto usando el método withoutSyncingToSearch. Este método acepta un solo cierre que se ejecutará de inmediato. Cualquier operación de modelo que ocurra dentro del cierre no se sincronizará con el índice del modelo:

use App\Models\Order;
 
Order::withoutSyncingToSearch(function () {
// Realiza acciones en el modelo...
});

Instancias de Modelo Condicionalmente Buscables

A veces, es posible que solo desees hacer un modelo buscable bajo ciertas condiciones. Por ejemplo, imagina que tienes un modelo App\Models\Post que puede estar en uno de dos estados: "borrador" y "publicado". Es posible que solo desees permitir que los mensajes "publicados" sean buscables. Para lograr esto, puedes definir un método shouldBeSearchable en tu modelo:

/**
* Determina si el modelo debe ser searchable (buscable).
*/
public function shouldBeSearchable(): bool
{
return $this->isPublished();
}

El método shouldBeSearchable solo se aplica al manipular modelos a través de los métodos guardar y crear, consultas o relaciones. Hacer directamente modelos o colecciones buscables usando el método searchable anulará el resultado del método shouldBeSearchable.

Advertencia El método shouldBeSearchable no es aplicable al usar el motor "database" de Scout, ya que todos los datos buscables siempre se almacenan en la base de datos. Para lograr un comportamiento similar al usar el motor de base de datos, deberías usar cláusulas where en su lugar.

Búsqueda

Puedes comenzar a buscar un modelo usando el método search. El método de búsqueda acepta una sola cadena que se utilizará para buscar tus modelos. Luego, debes encadenar el método get en la consulta de búsqueda para recuperar los modelos Eloquent que coinciden con la cadena de búsqueda dada:

use App\Models\Order;
 
$orders = Order::search('Star Trek')->get();

Dado que las búsquedas de Scout devuelven una colección de modelos Eloquent, incluso puedes devolver los resultados directamente desde una ruta o controlador y se convertirán automáticamente a JSON:

use App\Models\Order;
use Illuminate\Http\Request;
 
Route::get('/search', function (Request $request) {
return Order::search($request->search)->get();
});

Si deseas obtener los resultados de búsqueda en bruto antes de convertirlos en modelos Eloquent, puedes usar el método raw:

$orders = Order::search('Star Trek')->raw();

Índices Personalizados

Las consultas de búsqueda normalmente se realizarán en el índice especificado por el método searchableAs del modelo. Sin embargo, puedes usar el método within para especificar un índice personalizado que se debe buscar en su lugar:

$orders = Order::search('Star Trek')
->within('tv_shows_popularity_desc')
->get();

Claúsulas Where

Scout te permite agregar simples cláusulas "where" a tus consultas de búsqueda. Actualmente, estas cláusulas solo admiten comprobaciones básicas de igualdad numérica y son principalmente útiles para acotar las consultas de búsqueda por un ID de propietario:

use App\Models\Order;
 
$orders = Order::search('Star Trek')->where('user_id', 1)->get();

Además, se puede utilizar el método whereIn para verificar que el valor de una columna dada esté contenido dentro de la matriz dada:

$orders = Order::search('Star Trek')->whereIn(
'status', ['open', 'paid']
)->get();

El método whereNotIn verifica que el valor de la columna dada no esté contenido en la matriz dada:

$orders = Order::search('Star Trek')->whereNotIn(
'status', ['closed']
)->get();

Dado que un índice de búsqueda no es una base de datos relacional, las cláusulas "where" más avanzadas actualmente no son compatibles.

Advertencia Si tu aplicación usa Meilisearch, debes configurar los atributos filtrables antes de utilizar las cláusulas "where" de Scout.

Paginación

Además de recuperar una colección de modelos, puedes paginar tus resultados de búsqueda usando el método paginate. Este método devolverá una instancia de Illuminate\Pagination\LengthAwarePaginator de la misma manera que si hubieras paginado una consulta Eloquent tradicional:

use App\Models\Order;
 
$orders = Order::search('Star Trek')->paginate();

Puedes especificar cuántos modelos recuperar por página pasando la cantidad como el primer argumento al método paginate:

$orders = Order::search('Star Trek')->paginate(15);

Una vez que hayas recuperado los resultados, puedes mostrar los resultados y renderizar los enlaces de página usando Blade de la misma manera que si hubieras paginado una consulta Eloquent tradicional:

<div class="container">
@foreach ($orders as $order)
{{ $order->price }}
@endforeach
</div>
 
{{ $orders->links() }}

Por supuesto, si deseas recuperar los resultados de paginación como JSON, puedes devolver la instancia del paginador directamente desde una ruta o controlador:

use App\Models\Order;
use Illuminate\Http\Request;
 
Route::get('/orders', function (Request $request) {
return Order::search($request->input('query'))->paginate(15);
});

Advertencia Dado que los motores de búsqueda no son conscientes de las definiciones de alcance global de tu modelo Eloquent, no debes utilizar alcances globales en aplicaciones que utilizan la paginación de Scout. O, debes recrear las restricciones del alcance global al buscar a través de Scout.

Eliminación Suave

Si tus modelos indexados están eliminados suavemente y necesitas buscar tus modelos eliminados suavemente, establece la opción soft_delete en el archivo de configuración config/scout.php en true:

'soft_delete' => true,

Cuando esta opción de configuración es true, Scout no eliminará los modelos eliminados suavemente del índice de búsqueda. En su lugar, establecerá un atributo oculto __soft_deleted en el registro indexado. Luego, puedes usar los métodos withTrashed u onlyTrashed para recuperar los registros eliminados suavemente al buscar:

use App\Models\Order;
 
// Incluye registros eliminados al recuperar resultados...
$orders = Order::search('Star Trek')->withTrashed()->get();
 
// Solo incluye registros eliminados al recuperar resultados...
$orders = Order::search('Star Trek')->onlyTrashed()->get();

Nota Cuando se elimina permanentemente un modelo eliminado suavemente utilizando forceDelete, Scout lo eliminará automáticamente del índice de búsqueda.

Personalización de Búsquedas de Motores

Si necesitas realizar una personalización avanzada del comportamiento de búsqueda de un motor, puedes pasar un cierre como segundo argumento al método search. Por ejemplo, podrías usar esta devolución de llamada para agregar datos de geo-localización a tus opciones de búsqueda antes de que se pase la consulta de búsqueda a Algolia:

use Algolia\AlgoliaSearch\SearchIndex;
use App\Models\Order;
 
Order::search(
'Star Trek',
function (SearchIndex $algolia, string $query, array $options) {
$options['body']['query']['bool']['filter']['geo_distance'] = [
'distance' => '1000km',
'location' => ['lat' => 36, 'lon' => 111],
];
 
return $algolia->search($query, $options);
}
)->get();

Personalización de la Consulta de Resultados Eloquent

Después de que Scout recupera una lista de modelos Eloquent coincidentes de tu motor de búsqueda de la aplicación, Eloquent se utiliza para recuperar todos los modelos coincidentes por sus claves principales. Puedes personalizar esta consulta invocando el método query. El método query acepta un cierre que recibirá la instancia del generador de consultas Eloquent como argumento:

use App\Models\Order;
use Illuminate\Database\Eloquent\Builder;
 
$orders = Order::search('Star Trek')
->query(fn (Builder $query) => $query->with('invoices'))
->get();

Dado que esta devolución de llamada se invoca después de que los modelos relevantes ya se han recuperado de tu motor de búsqueda de la aplicación, el método query no debe usarse para "filtrar" resultados. En su lugar, debes usar cláusulas where de Scout.

Motores Personalizados

Creación del Motor

Si ninguno de los motores de búsqueda integrados de Scout se ajusta a tus necesidades, puedes escribir tu propio motor personalizado y registrarlo con Scout. Tu motor debe extender la clase abstracta Laravel\Scout\Engines\Engine. Esta clase abstracta contiene ocho métodos que tu motor personalizado debe implementar:

use Laravel\Scout\Builder;
 
abstract public function update($models);
abstract public function delete($models);
abstract public function search(Builder $builder);
abstract public function paginate(Builder $builder, $perPage, $page);
abstract public function mapIds($results);
abstract public function map(Builder $builder, $results, $model);
abstract public function getTotalCount($results);
abstract public function flush($model);

Puede resultarte útil revisar las implementaciones de estos métodos en la clase Laravel\Scout\Engines\AlgoliaEngine. Esta clase te proporcionará un buen punto de partida para aprender cómo implementar cada uno de estos métodos en tu propio motor.

Registro del Motor

Una vez que hayas escrito tu motor personalizado, puedes registrarlo en Scout usando el método extend del administrador de motores de Scout. Puedes resolver el administrador de motores de Scout desde el contenedor de servicios de Laravel. Debes llamar al método extend desde el método boot de tu clase App\Providers\AppServiceProvider o cualquier otro proveedor de servicios utilizado por tu aplicación:

use App\ScoutExtensions\MySqlSearchEngine;
use Laravel\Scout\EngineManager;
 
/**
* Inicializa los servicios de la aplicación.
*/
public function boot(): void
{
resolve(EngineManager::class)->extend('mysql', function () {
return new MySqlSearchEngine;
});
}

Una vez que tu motor haya sido registrado, puedes especificarlo como tu controlador Scout driver predeterminado en el archivo de configuración config/scout.php de tu aplicación:

'driver' => 'mysql',