Saltar al contenido principal

Introducción

Hay varias formas de añadir búsqueda a una aplicación en función de las necesidades. Laravel proporciona herramientas integradas que cubren desde coincidencia por palabras clave hasta búsqueda semántica con IA, sin necesidad de servicios externos.

Comparativa

FunciónServicio externoCaracterísticas
whereFullTextNoÍndice de texto completo integrado en MariaDB / MySQL / PostgreSQL
whereVectorSimilarToNo (PostgreSQL + pgvector)Búsqueda por similitud semántica. Requiere AI SDK
RerankingProveedor de IAReordena cualquier conjunto de resultados por relevancia con IA
Laravel ScoutNo (motor database) / opcionalSincroniza automáticamente los modelos Eloquent con el índice

Búsqueda de texto completo

Las consultas LIKE funcionan para coincidencias parciales sencillas, pero no entienden el idioma. La búsqueda de texto completo usa índices dedicados que tienen en cuenta límites de palabra, flexiones y puntuación de relevancia. MariaDB, MySQL y PostgreSQL admiten búsqueda de texto completo integrada, sin necesidad de servicios externos.
La búsqueda de texto completo está soportada en MariaDB, MySQL y PostgreSQL.

Añadir un índice full-text

Añade un índice full-text a las columnas objetivo.
Schema::create('articles', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('body');
    $table->timestamps();

    $table->fullText(['title', 'body']); // Índice compuesto
});
En PostgreSQL puedes indicar el idioma del índice. En idiomas distintos del inglés cambia el tratamiento de las flexiones.
$table->fullText('body')->language('english');
Consulta Migraciones para los detalles.
Notas sobre búsqueda de texto en japonés
La búsqueda de texto en japonés con MySQL tiene ciertas limitaciones. En AWS RDS solo está disponible el parser N-gram y no se puede añadir el plugin de análisis morfológico (MeCab). El MySQL de Laravel Cloud probablemente tenga las mismas limitaciones. En PostgreSQL el soporte para flexiones en japonés también es limitado. Si la precisión en japonés es crítica, considera motores dedicados como Meilisearch o Typesense.

Ejecutar consultas full-text

Con el índice creado, busca con whereFullText. Laravel genera el SQL adecuado según el driver (MATCH(...) AGAINST(...) en MariaDB/MySQL, to_tsvector(...) @@ plainto_tsquery(...) en PostgreSQL).
$articles = Article::whereFullText('body', 'web developer')->get();
Con un índice compuesto, pasa el mismo array de columnas.
$articles = Article::whereFullText(
    ['title', 'body'], 'web developer'
)->get();
En MariaDB/MySQL los resultados se ordenan automáticamente por relevancia. En PostgreSQL whereFullText solo filtra los registros que coinciden, sin ordenar por relevancia. Para orden automático por relevancia en PostgreSQL, el motor database de Scout es útil.
El método orWhereFullText permite añadir la búsqueda como condición OR. Consulta el query builder.

Búsqueda semántica / vectorial

La búsqueda de texto completo depende de la coincidencia de palabras. La búsqueda vectorial usa un enfoque distinto: representa el significado del texto como un array numérico (embedding) generado por IA y busca resultados semánticamente cercanos. Por ejemplo, la consulta “best wineries in Napa Valley” puede encontrar el artículo titulado “Top Vineyards to Visit” aunque no coincidan las palabras, porque su significado es cercano.
La búsqueda vectorial requiere el AI SDK de Laravel y soporta PostgreSQL (con la extensión pgvector) y MongoDB (con el paquete Laravel MongoDB). En Laravel Cloud todos los Postgres tienen pgvector ya preinstalado.

Generación de embeddings

Un embedding es un array numérico de alta dimensión (normalmente cientos o miles de dimensiones) que representa el significado del texto. Genera embeddings con toEmbeddings de la clase Stringable.
use Illuminate\Support\Str;

$embedding = Str::of('Napa Valley has great wine.')->toEmbeddings();
Para procesar varias cadenas a la vez es más eficiente usar Embeddings (solo una llamada a la API).
use Laravel\Ai\Embeddings;

$response = Embeddings::for([
    'Napa Valley has great wine.',
    'Laravel is a PHP framework.',
])->generate();

$response->embeddings; // [[0.123, 0.456, ...], [0.789, 0.012, ...]]
Consulta la documentación del AI SDK para la configuración de proveedores y las dimensiones.

Almacenamiento e indexación de vectores

Para guardar los embeddings define una columna vector en la migración. Ajusta dimensions a la salida del proveedor (p. ej., text-embedding-3-small de OpenAI: 1536 dimensiones). Llama a index() para crear un índice HNSW que acelera la búsqueda por similitud en grandes volúmenes.
Schema::ensureVectorExtensionExists(); // Habilita la extensión pgvector

Schema::create('documents', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('content');
    $table->vector('embedding', dimensions: 1536)->index();
    $table->timestamps();
});
En el modelo Eloquent castea la columna a array para automatizar la conversión entre PHP y el formato vectorial.
protected function casts(): array
{
    return [
        'embedding' => 'array',
    ];
}
Consulta Migraciones para los detalles de columnas e índices vectoriales.

Búsqueda por similitud

Con embeddings guardados, busca similares con whereVectorSimilarTo. Se compara con similitud coseno, se filtran los resultados por debajo del umbral minSimilarity y se ordenan automáticamente por relevancia. El umbral va de 0.0 a 1.0 (siendo 1.0 coincidencia exacta).
$documents = Document::query()
    ->whereVectorSimilarTo('embedding', $queryEmbedding, minSimilarity: 0.4)
    ->limit(10)
    ->get();
Si pasas una cadena en lugar del array de embedding, Laravel genera automáticamente el embedding. Puedes pasar directamente la consulta del usuario.
$documents = Document::query()
    ->whereVectorSimilarTo('embedding', 'best wineries in Napa Valley')
    ->limit(10)
    ->get();
Para más control existen whereVectorDistanceLessThan, selectVectorDistance y orderByVectorDistance. Consulta el query builder y la documentación del AI SDK.

Rerank

El rerank consiste en que un modelo de IA reordena un conjunto de resultados por relevancia respecto a la consulta. A diferencia de la búsqueda vectorial, no necesitas calcular y guardar embeddings; se aplica sobre cualquier colección de textos. El patrón “buscar → rerank” es especialmente eficaz: filtras rápido muchos registros con full-text y luego aplicas rerank con IA. Combina la velocidad de la BD con la precisión de la IA.
use Laravel\Ai\Reranking;

$response = Reranking::of([
    'Django is a Python web framework.',
    'Laravel is a PHP web application framework.',
    'React is a JavaScript library for building user interfaces.',
])->rerank('PHP frameworks');

$response->first()->document; // "Laravel is a PHP web application framework."
Las colecciones de Laravel tienen la macro rerank, que permite reordenar resultados Eloquent pasando un campo (o closure) y la consulta.
$articles = Article::all()
    ->rerank('body', 'Laravel tutorials');
Consulta la documentación del AI SDK para configurar el proveedor de reranking y las opciones disponibles.

Laravel Scout

Todas las técnicas anteriores llamaban directamente al query builder. Laravel Scout toma otro enfoque: al añadir el trait Searchable a un modelo Eloquent, Scout mantiene sincronizados los índices de búsqueda con la creación/actualización/eliminación de registros.

Motor database

El motor database de Scout usa búsqueda full-text y consultas LIKE sobre la base de datos existente. No necesita servicios externos ni infraestructura adicional. En toSearchableArray defines las columnas indexables. Los atributos PHP permiten indicar la estrategia por columna.
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Attributes\SearchUsingFullText;
use Laravel\Scout\Attributes\SearchUsingPrefix;
use Laravel\Scout\Searchable;

class Article extends Model
{
    use Searchable;

    #[SearchUsingPrefix(['id'])]
    #[SearchUsingFullText(['title', 'body'])]
    public function toSearchableArray(): array
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'body' => $this->body,
        ];
    }
}
AtributoEstrategia
SearchUsingFullTextUsa índice full-text (MATCH...AGAINST / to_tsvector)
SearchUsingPrefixPrefijo (example%)
NingunoComodines por ambos lados (%example%)
Las columnas con SearchUsingFullText requieren un índice full-text.
Añadido el trait, busca con search. El motor database de Scout devuelve resultados ordenados por relevancia también en PostgreSQL.
$articles = Article::search('Laravel')->get();

Motores de terceros

Scout también soporta motores de búsqueda como Algolia, Meilisearch o Typesense. Ofrecen tolerancia a errores tipográficos, búsqueda facetada, geobúsqueda, ranking personalizado, etc. Scout ofrece una API unificada, por lo que migrar del motor database a uno de terceros implica cambios de código mínimos.
La mayoría de aplicaciones no necesitan un motor externo. Las técnicas integradas de esta página cubren la mayor parte de los casos.
Consulta la guía de Laravel Scout.

Combinación de técnicas

Las técnicas anteriores no son excluyentes; combinándolas se obtienen los mejores resultados.

Full-text + rerank

Filtra candidatos rápido con full-text y reordénalos por relevancia semántica con rerank. Combina velocidad de la BD y precisión de la IA.
$articles = Article::query()
    ->whereFullText('body', $request->input('query'))
    ->limit(50)
    ->get()
    ->rerank('body', $request->input('query'), limit: 10);

Búsqueda vectorial + filtros clásicos

Combina similitud vectorial con where normales para acotar a un subconjunto (por equipo, categoría…) mientras haces búsqueda semántica.
$documents = Document::query()
    ->where('team_id', $user->team_id)
    ->whereVectorSimilarTo('embedding', $request->input('query'))
    ->limit(10)
    ->get();

Páginas relacionadas

Laravel Scout

Guía completa para sincronizar automáticamente los modelos con el trait Searchable.

Laravel AI SDK

Configuración del AI SDK necesaria para embeddings y reranking.

Query Builder

Detalles de whereFullText, whereVectorSimilarTo y demás métodos.

Migraciones

Cómo crear índices full-text y columnas vectoriales.
Última modificación el 13 de julio de 2026