Laravel Elasticsearch
Selam dostlar, bu yazımda Laravelde Elasticsearch kullanımından bahsedeceğim.
Elasticsearch, Apache Lucene üzerinde geliştirilmiş açık kaynak kodlu, RESTful, dağıtılmış arama ve analitik altyapısıdır. Elasticsearch, yayımlandığı 2010 yılından itibaren en popüler arama altyapısı haline gelmiştir ve genellikle günlük analitiği, tam metin arama, güvenlik zekası, iş analitiği ve operasyonel zeka kullanım örnekleri için tercih edilmektedir.
Hızlı aramalara cevap vermek için kullanılıyor. Binlerce kayıt içerinden filtreleme yapma maliyetini ve Sql’de ki response time’ı düşündüğümüzde Elasticsearch can kurtarıcı olarak devreye giriyor.
Kurulum
Sisteminizde kurulu Laravel projesi ve Elasticsearch olduğunu ve MySql vb konfigürasyonların yapıldığını var sayıyorum. Kurulu değilse Elasticsearch kurlum dökümanını takip edebilir veya sizin için hazırladığım Laravel & Elasticsearch example reposundan ilerleyebilirsiniz.
Sanal Veri Türetme
İşlemleri test edebilmek için verilere ihtiyacımız olacak. Laravel ‘in standart kurulumda gelen User tablosunu kullanacağım. Faker kullanarak 1000 tane kullanıcı oluşturun.
public function run()
{
// laravel 7
factory(App\User::class,1000)->create();
// laravel 8
User::factory(1000)->create();
}
php artisan db:seed
Artık User tablomuzda 1000 kullanıcı kaydı var.
Elastic Migrations
Bir veritabanı ve kullanıcılar tablosu oluşturduk. Şimdi Laravel’e Elasticsearch driver’ını kurmaya başlayalım. Şimdi arama motoru verilerini depolamak için bir Elasticsearch indeksi oluşturmanın zamanı geldi. Bir indeks, ilişkisel bir veritabanındaki bir tablo gibidir. Alan türlerini tanımlayan bir eşlemeye sahiptir. Bu paket sayesinde DB migration oluşturur gibi Elasticsearch migration’ları oluşturacağız.
composer require babenkoivan/elastic-migrations
Elastic Migrations, bağımlılık olarak Elastic Client kullanır. Bu, bir geçişi gerçekleştirmeden önce istemciyi .env dosyasında yapılandırmamız gerektiği anlamına gelir:
Elastic Migrations, paketi Elastic Client paketini kullanır. Elastic Client ise Elasticsearch’e bağlanabilmek için host ve port bilgisine ihtiyac duyar. Bu tanımlamayı .env
dosyasında yapacağız.
ELASTIC_HOST=elasticsearch:9200
Elastic Migrations meta bilgilerini depolamak için bir veritabanı tablosu kullandığından DB migration çalıştırmak gerek.
php artisan migrate
Şimdi Elasticsearch migration oluşturabiliriz.
php artisan elastic:make:migration create_users_index
Bu komut elastic/migrations
içinde _create_users_index.php
dosyasını oluşturacak.
declare(strict_types=1);
use ElasticAdapter\Indices\Mapping;
use ElasticAdapter\Indices\Settings;
use ElasticMigrations\Facades\Index;
use ElasticMigrations\MigrationInterface;
final class CreateUsersIndex implements MigrationInterface
{
/**
* Run the migration.
*/
public function up(): void
{
Index::create('users', function (Mapping $mapping, Settings $settings) {
$mapping->text('name');
$mapping->keyword('email');
});
}
/**
* Reverse the migration.
*/
public function down(): void
{
Index::dropIfExists('users');
}
}
Yukarıda görebileceğiniz gibi, kullanıcı dizinine yalnızca iki alan ekledik, name ve email.
Name alanı Elasticsearch tarafından analiz edilen ve full text sorgularında kullanılabilen text tipindedir. Email bir keyword (anahtar kelimedir), analiz edilmez ve çoğunlukla filtreleme için kullanılır. Artık search ederken name ve email kolonlarından kayıt araması yapılabilir.
Migration hazır olduğuna göre artık çalıştırabiliriz.
php artisan elastic:migrate
Bir sonraki adım, kullanıcı verilerini indekslemektir. Bu işlemi yapabilmek için Elastic Scout Driver kullanılmalıdır.
Elastic Scout Driver
Laravel Scout, Eloquent modellerinizi aranabilir hale getirecak. Scout, arama indekslerini veritabanı kayıtlarıyla otomatik olarak senkronize tutar.
Scout, Laravel‘in içinde gelmediğinden composer yardımıyla kurmak gerekir.
composer require laravel/scout
Bir çok Elasticsearch Scout sürücüsü içinden babenkoivan/elastic-scout-driver paketini kullanabilirisiniz.
composer require babenkoivan/elastic-scout-driver
.env
dosyasında SCOUT_DRIVER
değişkenini ayarlayarak sürücüyü etkinleştirebilirsiniz.
SCOUT_DRIVER=elastic
Şimdi User modelinin yapılandırmak gerekecek. Searchable trait ekleyerek arama özelliğini etkinleştirmemiz gerekir.
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Scout\Searchable;
class User extends Authenticatable
{
use Searchable, Notifiable;
public function toSearchableArray()
{
return [
'name' => $this->name,
'email' => $this->email,
];
}
}
Son olarak, User verilerini Elasticsearch’e aktarmaya hazırız.
php artisan scout:import "App\Models\User"
Tkinder aracıyla Elasticsearch’te kayıtlı bir kullanıcıyı bulalım.
php artisan tinker
User::search('Danika')->first();
Yukarıdaki isteğin çıktısı aşağıdaki gibi olacaktır.
App\Models\User {#4339
id: 4,
name: "Danika Heaney",
email: "xcasper@example.org",
email_verified_at: "2021-01-19 12:49:05",
created_at: "2021-01-19 12:49:09",
updated_at: "2021-01-19 12:49:09",
}
Elastic Scout Driver Plus
Elastic Scout Driver oldukça güzeldir, yalnız Scout’un özellikleriyle sınırlıdır. Daha detaylı kullanım için Elastic Scout Driver Plus kullanın.
composer require babenkoivan/elastic-scout-driver-plus
Paket kurulumu tamamlandıktan sonra App\Models\User
içerisinde kullandığımız Laravel\Scout\Searchable
trait’ini ElasticScoutDriverPlus\Searchable
ile değiştirin.
Artık aşağıdaki kodu deneyebilirisiniz.
$query = Query::match()->field('name')->query('Danika')->fuzziness('AUTO');
$userList = User::searchQuery($query)->execute()->models()->sortBy('id')->toArray();
Ekran çıktısı aşağıdaki gibi olacaktır.
App\Models\User {#4388
id: 4,
name: "Danika Heaney",
email: "xcasper@example.org",
email_verified_at: "2021-01-19 12:49:05",
created_at: "2021-01-19 12:49:09",
updated_at: "2021-01-19 12:49:09",
}
Kaydı search’e ekle
Yeni bir kaydı elasticsearch’e eklemek istediğinizde searchable
methodunu kullanabilirsiniz.
User::find(101)->searchable();
Kaydı search’ten kaldır
Mevcut kaydı elasticsearch’ten silmek istediğinizde unsearchable
methodunu kullanabilirsiniz.
User::find(101)->unsearchable();
Elinize sağlık, bilgilendirici bir doküman olmuş.