PHP code example of hilsonxhero / elasticvision

1. Go to this page and download the library: Download hilsonxhero/elasticvision library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

hilsonxhero / elasticvision example snippets


return [
    'indexes' => [
        \App\Models\Product::class,
    ],
];

use App\Models\Post;

$posts = Post::search('lorem')
    ->filter(new Term('published', true))
    ->get();

use App\Models\Post;

$posts = Post::search('lorem')
    ->should(new Terms('tags', ['featured'], 2))
    ->get();

use App\Models\Post;

$results = Post::search('Self-steering')
    ->orderBy('published_at', 'desc')
    ->get();

use App\Models\User;

$results = User::search('fugiat')->must(new Range('age',['gte' => 18, 'lte' => 35]))->get();

use App\Models\User;

$results = User::search('fugiat')->must(new RegExp('username', 'k.*y','ALL',false))->get();

use App\Models\User;

$users = User::search()
    ->should(new Wildcard('username','ki*y'))
    ->get();

use App\Models\Article;

$articles = Article::search()
    ->must(new Matching('title','ipsum'))
    ->get();

use App\Models\User;

$users = User::search()
    ->should(new MatchPhrasePrefix('message','quick brown f'))
    ->get();

use App\Models\User;

$users = User::search()
    ->should(new MatchPhrase('message','this is a test'))
    ->get();

use App\Models\Product;

$products = Product::search()
    ->must(new Nested('category', new Term('category.id', 2)))
    ->get();

use App\Models\Product;

$search = Product::search("lorem");

// $feature_ids = array([4 => [1,2], 5 => [1,2]])

foreach (request()->feature_id as $key => $value) {
  $query = new BoolQuery();
  $query->must(new Term('features.feature_id', $key));
  $query->must(new Terms('features.feature_value_id', $value));
  $boolQuery->add('must', new Nested('features', $query));
}

 $search->newCompound($boolQuery);

 $products = $search->paginate(15);



namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Hilsonxhero\ElasticVision\Application\Explored;
use Hilsonxhero\ElasticVision\Application\IndexSettings;
use Laravel\Scout\Searchable;

class Post extends Model implements Explored, IndexSettings
{
    use HasFactory;
    use Searchable;

    protected $fillable = ['title', 'published'];

    public function mappableAs(): array
    {
        return [
            'id' => 'keyword',
            'title' => 'text',
            'published' => 'boolean',
            'created_at' => 'date',
        ];
    }

    public function indexSettings(): array
    {
        return [
            'analysis' => [
                'analyzer' => [
                    'standard_lowercase' => [
                        'type' => 'custom',
                        'tokenizer' => 'standard',
                        'filter' => ['lowercase'],
                    ],
                ],
            ],
        ];
    }
}



namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Hilsonxhero\ElasticVision\Application\Explored;
use Hilsonxhero\ElasticVision\Application\IndexSettings;
use Hilsonxhero\ElasticVision\Domain\Analysis\Analysis;
use Hilsonxhero\ElasticVision\Domain\Analysis\Analyzer\StandardAnalyzer;
use Hilsonxhero\ElasticVision\Domain\Analysis\Filter\SynonymFilter;
use Laravel\Scout\Searchable;

class Post extends Model implements Explored, IndexSettings
{
    use HasFactory;
    use Searchable;

    protected $fillable = ['title', 'published'];

    public function mappableAs(): array
    {
        return [
            'id' => 'keyword',
            'title' => [
                'type' => 'text',
                'analyzer' => 'frameworks',
            ],
            'published' => 'boolean',
            'created_at' => 'date',
        ];
    }

    public function indexSettings(): array
    {
        $synonymFilter = new SynonymFilter();
        $synonymFilter->setSynonyms(['vue => react']);

        $synonymAnalyzer = new StandardAnalyzer('frameworks');
        $synonymAnalyzer->setFilters(['lowercase', $synonymFilter]);

        return (new Analysis())
            ->addAnalyzer($synonymAnalyzer)
            ->addFilter($synonymFilter)
            ->build();
    }
}

$search = Cartographer::search();
$search->aggregation('places', new TermsAggregation('place'));

$results = $search->raw();
$aggregations = $results->aggregations();

$categories = Category::search('lorem ipsum')->filter(new MatchPhrase('status', 'enable'))->take(15)->get();

class Product extends Model implements Explored
{
    public function mappableAs(): array
    {
        return [
            'id' => 'keyword',
            'title_fa' => [
                'type' => 'text',
                'analyzer' => 'my_analyzer',
            ],
            'title_en' => [
                'type' => 'text',
            ],
            'status' => [
                'type' => 'text',
            ],
            'category' => 'nested',
            'features' => 'nested',
            'variants' => 'nested',
            'has_stock' => 'boolean',
        ];
    }


    public function toSearchableArray(): array
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'status' => $this->status,
            'category' => $this->category,
            'features' => $this->features,
            'variants' => ProductVariantResource::collection($this->variants)->toArray(true),
            'has_stock' => $this->has_stock,
        ];
    }

    public function indexSettings(): array
    {
        return [
            "analysis" => [
                "analyzer" => [
                    "my_analyzer" => [
                        "type" => "custom",
                        "tokenizer" => "standard",
                        "filter" => ["lowercase", "my_filter"]
                    ]
                ],
                "filter" => [
                    "my_filter" => [
                        "type" => "ngram",
                        "min_gram" => 2,
                    ]
                ]
            ],
            "index" => [
                "max_ngram_diff" => 13
            ]
        ];
    }

    /**
     * Get the name of the index associated with the model.
     *
     * @return string
     */
    public function searchableAs()
    {
        return 'products';
    }

    public function category()
    {
        return $this->belongsTo(Category::class);
    }

    public function variants()
    {
        return $this->hasMany(ProductVariant::class);
    }
        public function features()
    {
        return $this->hasMany(ProductFeature::class);
    }

    /**
     * check inventory of product variations
     *
     * @return \Illuminate\Database\Eloquent\Casts\Attribute
     */

    protected function hasStock(): Attribute
    {
        return Attribute::make(
            get: fn ($value) => $this->variants()->sum('stock') > 0 ? true : false
        );
    }

}



        $boolQuery = new BoolQuery();

        $search = Product::search("ipsum")
            ->field('title')
            ->field('description')
            ->filter(new MatchPhrase('status', 'enable'))
            ->must(new Nested('category', new MatchPhrase('category.id',2)));

        if (request()->filled('available_stock')) {
            $search->filter(new Term('has_stock', true));
        }

        // request feature_ids value

        // $feature_ids = array([4 => [1,2], 5 => [1,2]])

        if (request()->filled('feature_ids')) {
            foreach (request()->feature_ids as $key => $value) {
                $query = new BoolQuery();
                $query->must(new MatchPhrase('features.feature_id', $key));
                $query->must(new Terms('features.feature_value_id', $value));
                $boolQuery->add('must', new Nested('features', $query));
            }
        }

        if (request()->filled('max_price') && request()->filled('min_price')) {
            $boolQuery->add('must', new Nested('variants', new Range(
                'variants.selling_price',
                ['gte' => request()->min_price]
            )));
            $boolQuery->add('must', new Nested('variants', new Range(
                'variants.selling_price',
                ['lte' => request()->max_price]
            )));
            $boolQuery->add('must_not', new Nested('variants', new Range(
                'variants.selling_price',
                ['lt' => request()->min_price]
            )));
            $boolQuery->add('must_not', new Nested('variants', new Range(
                'variants.selling_price',
                ['gt' => request()->max_price]
            )));
        }

        $search->newCompound($boolQuery);

        $products = $search->paginate(15);

        return $products;

class SearchController
{
    public function __invoke(SearchFormRequest $request)
    {
        $people = Cartographer::search($request->get('keywords'))->get();

        return view('search', [
            'people' => $people,
        ]);
    }
}

use Hilsonxhero\ElasticVision\Infrastructure\Scout\ElasticEngine;

$debug = ElasticEngine::debug();

$lastQueryAsArray = ElasticEngine::debug()->array();
$lastQueryAsJson = ElasticEngine::debug()->json();
bash
php artisan vendor:publish --tag=elasticvision-config
bash
php artisan scout:index products

php artisan elastic:update <index

php artisan elastic:update posts

php artisan scout:delete-index <model>