Teljes szöveges keresés implementálása Laravel Scout-tal

Manapság egyetlen modern webalkalmazás sem képzelhető el hatékony kereső funkció nélkül. Legyen szó e-kereskedelmi oldalról, blogról, dokumentumkezelő rendszerről vagy bármilyen adatvezérelt platformról, a felhasználók elvárják, hogy gyorsan és pontosan megtalálják, amit keresnek. A hagyományos adatbázis-lekérdezések (mint a LIKE %kulcsszó%) sok esetben lassúak és pontatlanok, különösen nagy adatmennyiségnél vagy összetett keresési igények esetén. Itt jön képbe a teljes szöveges keresés, amely lehetővé teszi, hogy az alkalmazás nem csak a pontos egyezéseket, hanem a releváns találatokat is megtalálja a szöveges adatokban.

A Laravel ökoszisztémája, mint mindig, most is kínál egy elegáns megoldást erre a problémára: a Laravel Scout csomagot. A Scout egy meghajtóalapú megoldás, amely absztrahálja a mögöttes keresőmotor komplexitását, és egységes, kifejező API-t biztosít a Laravel Eloquent modelljei közötti kereséshez. Ebben az átfogó útmutatóban lépésről lépésre végigmegyünk a Laravel Scout implementálásán, megvizsgáljuk a különböző keresési illesztőprogramokat, és bemutatjuk, hogyan hozhatunk létre robusztus és villámgyors keresőfunkciót Laravel alkalmazásunkban.

Mi az a Laravel Scout, és miért van rá szükségünk?

A Laravel Scout egy hivatalos Laravel csomag, amely egyszerű módot biztosít arra, hogy hozzáadjunk teljes szöveges keresést az Eloquent modelljeinkhez. Lényegében egy absztrakciós réteg a különböző keresőmotorok (például Algolia, MeiliSearch, Elasticsearch) felett, lehetővé téve számunkra, hogy ugyanazzal az API-val dolgozzunk, függetlenül attól, hogy milyen keresőmotort használunk a háttérben. Ez azt jelenti, hogy ha például Algolia-ról MeiliSearch-re szeretnénk váltani, a kódunk nagy része érintetlen marad, mindössze a konfigurációs fájlt kell módosítanunk.

A hagyományos adatbázis keresési módszerek, mint az SQL LIKE operátor, számos hátránnyal járnak:

  • Teljesítményszűk keresztmetszet: Nagy adatbázisok esetén rendkívül lassúak lehetnek.
  • Relevancia hiánya: Nehéz velük rangsorolni a találatokat relevancia alapján.
  • Tolerancia hiánya: Nem kezelik jól a gépelési hibákat vagy a szinonimákat.
  • Komplexitás: Az összetettebb keresési igények (pl. faceting, autosuggest) megvalósítása rendkívül bonyolult.

A Laravel Scout és a mögötte álló speciális keresőmotorok ezeket a problémákat hidalják át, villámgyors, releváns és intelligens keresési élményt nyújtva a felhasználóknak.

Válasszunk megfelelő keresési illesztőprogramot (Search Driver)

A Scout egyik erőssége a modularitása. Számos keresési illesztőprogramot támogat, amelyek közül a legnépszerűbbek a következők:

  • Algolia: Egy felhőalapú, rendkívül gyors és funkciókban gazdag keresési szolgáltatás. Kiváló választás nagy projektekhez és komplex keresési igényekhez, de fizetős.
  • MeiliSearch: Egy nyílt forráskódú, rendkívül gyors és erőteljes keresőmotor, amelyet könnyű telepíteni és használni. Kiváló választás kisebb és közepes projektekhez, ahol fontos a sebesség és a releváns találatok. Költséghatékonyabb, mivel saját szerveren futtatható.
  • Elasticsearch: Egy másik népszerű, nyílt forráskódú, skálázható keresőmotor, amelyet általában nagyobb, big data alapú alkalmazásokban használnak. Komplexebb beállítást igényel.
  • Database Driver: Alapértelmezés szerint a Scout tartalmaz egy adatbázis illesztőprogramot is. Ez a meghajtó a LIKE %kulcsszó% lekérdezéseket hajtja végre az adatbázison. Kis adatmennyiség esetén hasznos lehet, de nem nyújt igazi teljes szöveges keresési képességeket és nem skálázódik jól.
  • Collection Driver: Laravel 9-től elérhető, ez az illesztőprogram a modell gyűjteményén hajtja végre a keresést a memóriában. Fejlesztési célokra vagy nagyon kis adathalmazokhoz hasznos, ahol nincs szükség perzisztens indexelésre.
  • TNTSearch: Egy nyílt forráskódú, fájlalapú keresőmotor, amelyet PHP-ban írtak. Egyszerűen telepíthető, de kisebb projektekhez ajánlott, és teljesítménye elmaradhat a dedikált keresőmotorokétól.

Projekttől függően választhatunk a fenti illesztőprogramok közül. Komoly teljes szöveges keresés implementálásához az Algolia vagy a MeiliSearch a leginkább ajánlott. Ebben az útmutatóban elsősorban a MeiliSearch-et fogjuk alapul venni, mivel nyílt forráskódú, gyors és könnyen beállítható.

Laravel Scout telepítése és konfigurálása

1. Telepítés Composerrel

Először telepítsük a Laravel Scout csomagot Composer segítségével:

composer require laravel/scout

2. Konfigurációs fájl publikálása

Ezt követően publikáljuk a Scout konfigurációs fájlját. Ez lehetővé teszi számunkra, hogy testreszabjuk a Scout működését:

php artisan vendor:publish --provider="LaravelScoutScoutServiceProvider"

Ez létrehozza a config/scout.php fájlt.

3. Környezeti változók beállítása (.env)

A .env fájlban beállíthatjuk a kívánt keresési illesztőprogramot. Ha például a MeiliSearch-et választjuk:

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

Ha Algolia-t használnánk, akkor az Algolia API kulcsokat kellene beállítanunk. Fontos, hogy minden kiválasztott illesztőprogramhoz telepítenünk kell a megfelelő Composer csomagot is (pl. composer require meilisearch/meilisearch-php).

4. Modell előkészítése

Ahhoz, hogy egy Eloquent modell kereshető legyen a Scouttal, hozzá kell adnunk a Searchable trait-et a modellhez:

use LaravelScoutSearchable;

class Post extends Model
{
    use Searchable;

    // ...
}

5. A `toSearchableArray()` metódus

A Searchable trait hozzáadásával a modell automatikusan szinkronizálódni fog a keresőmotorral. Alapértelmezetten a Scout az összes publikus oszlopot indexeli. Azonban gyakran szeretnénk finomhangolni, hogy mely adatok kerüljenek az indexbe. Ehhez felülírhatjuk a toSearchableArray() metódust a modellben:

use LaravelScoutSearchable;

class Post extends Model
{
    use Searchable;

    /**
     * Get the indexable data array for the model.
     *
     * @return array
     */
    public function toSearchableArray(): array
    {
        $array = $this->toArray();

        // Customize the data array for full-text search
        return [
            'id' => $this->id,
            'title' => $this->title,
            'content' => $this->content,
            'author_name' => $this->user->name, // Example of related data
            'tags' => $this->tags->pluck('name')->all(), // Example of collection data
        ];
    }
}

Ez a metódus határozza meg, hogy a modell mely attribútumai kerülnek a keresőmotor indexébe. A gondosan összeállított toSearchableArray() kulcsfontosságú a releváns keresési eredmények eléréséhez.

Keresés végrehajtása

Miután a modell felkészült a keresésre, rendkívül egyszerű a keresés végrehajtása:

$posts = Post::search('keresési kifejezés')->get();

foreach ($posts as $post) {
    echo $post->title;
}

Keresés szűrése és lapozás

A search() metódus további láncolható metódusokat is biztosít a szűréshez és lapozáshoz:

// Szűrés (pl. kategória alapján)
$posts = Post::search('keresési kifejezés')
             ->where('category_id', 1)
             ->get();

// Lapozás
$posts = Post::search('keresési kifejezés')
             ->paginate(10);

Fontos megjegyezni, hogy a where() metódusok a mögöttes keresőmotor szűrési képességeit használják, nem pedig az adatbázisét. Ez rendkívül hatékonnyá teszi a szűrést.

Haladó keresési funkciók és beállítások

Index nevének testreszabása

Ha a modell neve eltér attól, amit a keresőmotor indexének nevezni szeretnénk, felülírhatjuk a searchableAs() metódust:

public function searchableAs(): string
{
    return 'my_posts_index';
}

Feltételes indexelés

Néha nem minden modellpéldányt szeretnénk indexelni. A shouldBeSearchable() metódussal megadhatunk feltételeket:

public function shouldBeSearchable(): bool
{
    return $this->published && !$this->trashed();
}

Soft Deletes kezelése

Ha a modellünk használja a SoftDeletes trait-et, a Scout alapértelmezés szerint eltávolítja a törölt rekordokat az indexből. Ha azokat is kereshetővé szeretnénk tenni (pl. admin felületen), akkor a config/scout.php fájlban beállíthatjuk a soft_delete.enabled opciót true-ra.

Queues (Sorok) használata a teljesítményért

A modellek szinkronizálása a keresőmotorral időigényes művelet lehet, különösen, ha sok adatunk van, vagy külső szolgáltatást (pl. Algolia) használunk. A Laravel Scout támogatja a sorok (queues) használatát a teljesítmény javítása érdekében. Ehhez be kell állítanunk a SCOUT_QUEUE=true környezeti változót, és győződjünk meg róla, hogy a Laravel sorrendszere megfelelően van konfigurálva és fut:

// config/scout.php
'queue' => env('SCOUT_QUEUE', false),

Ha a sorok engedélyezve vannak, a modellek indexelése, frissítése és törlése aszinkron módon történik, nem blokkolva a felhasználói felületet.

Indexelés parancssorból

Amikor először állítjuk be a Scoutot, vagy ha módosítjuk a toSearchableArray() metódust, újra kell indexelnünk a meglévő adatokat. Ezt a következő Artisan paranccsal tehetjük meg:

php artisan scout:import "AppModelsPost"

Ez az összes Post modellt lekéri az adatbázisból, és feltölti a keresőmotor indexébe. A scout:flush paranccsal törölhetjük az index tartalmát.

MeiliSearch implementáció részletei

Ahogy korábban említettük, a MeiliSearch kiváló választás a teljes szöveges kereséshez. Íme, hogyan illeszthetjük be a Laravel Scout-tal:

1. MeiliSearch telepítése

A legegyszerűbb módja a MeiliSearch futtatásának a Docker:

docker run -it --rm -p 7700:7700 -e MEILI_MASTER_KEY='masterKey' getmeili/meilisearch:latest

Ez egy konténerben elindítja a MeiliSearch-et a 7700-as porton, egy megadott master kulccsal. Ne feledjük, hogy éles környezetben ezt egy tartós adat tárolással kellene konfigurálni.

2. MeiliSearch Laravel Scout illesztőprogram telepítése

composer require meilisearch/meilisearch-php

3. Környezeti változók beállítása

Ezt már korábban láttuk, de fontos újra hangsúlyozni:

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

4. MeiliSearch index beállításai

A MeiliSearch egy nagyon okos keresőmotor, de a legjobb eredmények eléréséhez érdemes konfigurálni az index beállításait. Ezeket a beállításokat a MeiliSearch API-ján keresztül (vagy egy admin felületen, mint pl. MeiliSense) végezzük, nem közvetlenül a Laravel Scouton keresztül. Fontosabb beállítások:

  • Searchable Attributes: Mely attribútumok legyenek kereshetők? (pl. ['title', 'content', 'tags'])
  • Displayed Attributes: Mely attribútumok jelenjenek meg a találatokban? (pl. ['id', 'title', 'content'])
  • Sortable Attributes: Mely attribútumok alapján lehessen rendezni a találatokat? (pl. ['created_at', 'title'])
  • Ranking Rules: Hogyan rangsorolja a MeiliSearch a találatokat? Ez befolyásolja a relevancia sorrendjét.
  • Stop Words: Mely szavakat ignorálja a keresés során? (pl. „a”, „az”, „és”)
  • Synonyms: Szinonimák beállítása (pl. „autó” és „gépjármű” azonosnak számítson).

Ezek a beállítások kulcsfontosságúak a releváns és pontos keresési eredményekhez. Például, ha egy `Post` modell `title` és `content` mezőjében szeretnénk keresni, akkor a MeiliSearch indexen a `searchableAttributes` beállítást így adhatjuk meg:

// Példa arra, hogyan konfigurálhatjuk az indexet MeiliSearch-ben (pl. egy Service Providerben)
use MeilisearchClient;

public function boot()
{
    $client = new Client(config('scout.meilisearch.host'), config('scout.meilisearch.key'));
    $index = $client->index((new AppModelsPost())->searchableAs());

    $index->updateSearchableAttributes([
        'title',
        'content',
        'author_name',
        'tags'
    ]);

    $index->updateDisplayedAttributes([
        'id',
        'title',
        'content',
        'author_name',
        'tags'
    ]);

    // ... egyéb beállítások
}

Ezeket a beállításokat általában egy Laravel Service Provider boot() metódusában érdemes elvégezni, vagy egy külön Artisan parancsban, hogy ne fussanak le minden kérésnél.

Frontend integráció

A teljes szöveges keresés funkcionalitása nem ér véget a backendben. A felhasználók számára valós idejű keresési élményt is biztosíthatunk.

Egyszerű űrlap alapú keresés

A legegyszerűbb megvalósítás egy HTML űrlap, amely a keresési kifejezést POST vagy GET kérésként küldi egy Laravel útvonalra. Ezen az útvonalon a kontroller a Post::search($request->input('query'))->paginate(10); metódussal lekérdezi a találatokat és megjeleníti őket.

Valós idejű (AJAX) keresés

A felhasználói élmény javítása érdekében implementálhatunk valós idejű keresést AJAX kérésekkel. A felhasználó gépelése közben küldhetünk kéréseket a szervernek, és azonnal megjeleníthetjük a találatokat. Ezt könnyedén megvalósíthatjuk JavaScript (pl. Vanilla JS, jQuery, Vue.js, React, Alpine.js) segítségével. A frontend komponens egy beviteli mező értékét küldi el egy API endpointra, amely a Scout segítségével keres, majd JSON formátumban visszaadja a találatokat.

// Példa fetch API-val egy valós idejű keresésre
document.getElementById('search-input').addEventListener('keyup', async (event) => {
    const query = event.target.value;
    if (query.length > 2) { // Keressünk csak 2 karakternél hosszabb bemenetre
        const response = await fetch(`/api/search?query=${query}`);
        const data = await response.json();
        // Frissítsd a keresési eredményeket a UI-n a 'data' alapján
        console.log(data);
    }
});

A Laravel oldalon ehhez létrehozhatunk egy API útvonalat és egy kontrollert, amely a Post::search($request->query('query'))->get(); vagy paginate() metódussal visszatér a találatokkal.

Legjobb gyakorlatok és tippek

  • Válassz okosan illesztőprogramot: Ne ragaszkodjunk a Database driverhez, ha komoly teljes szöveges keresésre van szükség. Fejlesztési környezetben kipróbálhatjuk a MeiliSearch-et, Algolia-t, és döntsünk a projekt igényei szerint.
  • Finomhangoljuk a toSearchableArray()-t: Csak a releváns adatokat indexeljük. Ne indexeljünk nagy méretű, nem releváns szövegeket, mert az lassíthatja a keresést és növelheti az index méretét.
  • Használjunk sorokat (Queues): Minden éles környezetben (production) futó alkalmazásban engedélyezzük a Scout sorokat a modellfrissítések és törlések aszinkron kezeléséhez.
  • Optimalizáljuk a keresőmotor beállításait: A MeiliSearch vagy Algolia esetében konfiguráljuk a szinonimákat, stop szavakat, rangsorolási szabályokat és releváns attribútumokat, hogy a keresési eredmények a lehető legpontosabbak legyenek.
  • Teszteljük alaposan: A különböző keresési kifejezésekkel, gépelési hibákkal és szinonimákkal történő tesztelés kulcsfontosságú a jó felhasználói élmény biztosításához.
  • Gondoljunk a skálázhatóságra: Ha az alkalmazás növekszik, a keresőmotornak is képesnek kell lennie kezelni a megnövekedett adatmennyiséget és keresési kéréseket. A MeiliSearch és Algolia ezen a téren is kiválóan teljesít.

Összefoglalás

A Laravel Scout rendkívül megkönnyíti a teljes szöveges keresés implementálását Laravel alkalmazásokban. Az absztrakciós rétegnek köszönhetően könnyedén integrálhatunk robusztus keresőmotorokat, mint az Algolia vagy a MeiliSearch, anélkül, hogy a mögöttes technológia komplexitásával kellene foglalkoznunk. A megfelelő keresési illesztőprogram kiválasztásával, a toSearchableArray() metódus okos használatával és a keresőmotor beállításainak finomhangolásával villámgyors és releváns keresési élményt nyújthatunk a felhasználóknak. Ne habozzon belevágni, és tegye alkalmazását még használhatóbbá a Laravel Scout erejével!

Leave a Reply

Az e-mail címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük