composer require romangrinev/laravel-opensearch-engine
Update your App\Providers\AppServiceProvider
<?php
namespace App\Providers;
// ...
use Grinev\LaravelOpenSearchEngine\OpenSearchEngine;
use Laravel\Scout\EngineManager;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
// ...
resolve(EngineManager::class)->extend(config('scout.driver'), function () {
return new OpenSearchEngine;
});
}
}
Update config\scout.php
<?php
return [
//
'driver' => env('SCOUT_DRIVER', 'opensearch'),
'opensearch' => [
'host' => env('OPENSEACH_HOST', 'http://localhost:9200'),
'user' => env('OPENSEACH_USER', 'admin'),
'pass' => env('OPENSEACH_PASS', 'admin'),
],
//
];
$posts = Post::search('Key phrase')->get();
$posts = Post::search()->orderBy('posted_at', 'desc')->get();
$posts = Post::search()->where('category_id', '48')->get();
$posts = Post::search()->where('range', [
'price' => [
'gte' => 100,
'lte' => 200
]
])->get();
Learn more about OpenSearch Range Queries
Here is more about OpenSearch Geo-bounding box queries
$posts = Post::search()->->where('geo_bounding_box', [
"location" => [
"top_left" => [
"lat" => 48.0,
"lon" => -123.0
],
"bottom_right" => [
"lat" => 46.0,
"lon" => -121.0
]
]
])->get();
In order to perform this type of seary make sure the mapping for the location
field is set as geo_point
in your config/scout.php
config file.
<?php
return [
//
'opensearch' => [
//
'mappings' => [
'posts_index' =>[
"mappings" => [
"properties" => [
"location" => [
"type" => "geo_point"
]
]
]
]
]
],
];
public function searchableAs(){
return 'posts_index';
}
public function toSearchableArray(){
$data = [
//
'location' => "{$this->lat},{$this->lng}",
];
return $data;
}
After changing scout.php
for mapping and updating the toSearchableArray()
make sure to update your OpenSearch index like this:
php artisan scout:flush App\\Models\\Post
php artisan scout:index App\\Models\\Post
php artisan scout:import App\\Models\\Post
This example shows how to group by / aggregate open search results.
$raw = Post::search('Key phrase')
->whereRaw([
'aggs' => [
'categories' => [
'terms' => [
'field' => 'category_id'
]
]
]
])->raw();
$categories = collect(data_get($raw, 'aggregations.categories.buckets', []))->pluck('key')->map(fn($id) => Category::find($id));
Learn more about OpenSearch Aggregations
Learn more about Laravel Scout