romangrinev/laravel-opensearch-engine

Custom Laravel Scout OpenSearch Engine

v0.0.14 2023-03-13 16:55 UTC

This package is not auto-updated.

Last update: 2024-04-22 22:19:01 UTC


README

Installation

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'),
    ],

    //
];

Usage

Search by keyphrase

$posts = Post::search('Key phrase')->get();

Order search results

$posts = Post::search()->orderBy('posted_at', 'desc')->get();

Search by term

$posts = Post::search()->where('category_id', '48')->get();

Search by range

$posts = Post::search()->where('range', [
    'price' => [
        'gte' => 100,
        'lte' => 200
    ]
])->get();

Learn more about OpenSearch Range Queries

Seach by geo location

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.

config/scout.php

<?php
return [
    //
    'opensearch' => [
        //
        'mappings' => [
            'posts_index' =>[
                "mappings" => [
                    "properties" => [
                        "location" => [
                            "type" => "geo_point"
                        ]
                    ]
                ]
            ]
        ]
    ],
];

app/models/Post.php

    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

Group By / Aggregate results

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