PHP code example of ponito / elastico

1. Go to this page and download the library: Download ponito/elastico 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/ */

    

ponito / elastico example snippets


'connections' => [
    'elasticsearch' => [
        'driver' => 'elastic',
        'hosts'  => [env('ELASTICSEARCH_HOST', 'http://localhost:9200')],
        // Optional auth
        'username' => env('ELASTICSEARCH_USERNAME'),
        'password'  => env('ELASTICSEARCH_PASSWORD'),
        // Optional TLS
        'certificate' => env('ELASTICSEARCH_CERT'),
        // Optional Elastic Cloud
        'cloud' => env('ELASTIC_CLOUD_ID'),
    ],
],

use Elastico\Eloquent\Model;
use Elastico\Index\Config;
use Elastico\Index\Mappings;
use Elastico\Mapping\Field;
use Elastico\Mapping\FieldType;

class Article extends Model
{
    protected $connection = 'elasticsearch';

    // The Elasticsearch index name
    protected $table = 'articles';

    protected $fillable = ['title', 'status', 'published_at', 'author_id', 'score'];

    public static function getIndexConfig(): Config
    {
        return Config::make('articles')
            ->mapping(fn(Mappings $m) => $m->properties(
                Field::make(FieldType::keyword, 'status'),
                Field::make(FieldType::keyword, 'author_id'),
                Field::make(FieldType::text,    'title'),
                Field::make(FieldType::date,    'published_at'),
                Field::make(FieldType::float,   'score'),
            ));
    }
}

// Create
$article = Article::create(['title' => 'Hello', 'status' => 'draft']);

// Find
$article = Article::find('doc-id');

// Update
$article->update(['status' => 'published']);

// Delete
$article->delete();

// Upsert (creates if missing, updates if present)
Article::upsert(
    [['_id' => 'doc-1', 'title' => 'Hello', 'status' => 'draft']],
    '_id'
);

// Equality → term query
Article::where('status', 'published')->get();

// Range → range query
Article::where('score', '>', 80)->get();
Article::where('score', '>=', 80)->where('score', '<', 100)->get();
Article::whereBetween('score', [80, 100])->get();   // exclusive bounds (gt/lt)

// Terms → terms query
Article::whereIn('status', ['published', 'featured'])->get();
Article::whereNotIn('status', ['deleted'])->get();

// Null / exists
Article::whereNull('published_at')->get();
Article::whereNotNull('published_at')->get();

// NOT equal
Article::where('status', '<>', 'deleted')->get();

// OR
Article::where('status', 'published')
       ->orWhere('status', 'featured')
       ->get();

// like → match query (strips % wildcards)
Article::where('title', 'like', '%elasticsearch%')->get();

Article::orderBy('published_at', 'desc')->get();

// With missing value handling
Article::orderBy('score', 'desc', missing: '_last')->get();

// With nested sort
Article::orderBy('comments.likes', 'desc', nested: ['path' => 'comments'])->get();

Article::limit(20)->offset(40)->get();
Article::paginate(20);

// Total hits are preserved even with limit
$results = Article::limit(10)->get();
$results->total(); // full match count

Article::select(['title', 'status'])->get();

// Exclude fields
Article::exclude(['body', 'raw_html'])->get();

// Return one result per unique author
Article::collapse('author_id')->get();

Article::suggest(
    name:  'title_suggest',
    text:  'elastcsearch',
    field: 'title',
    type:  'term',
    size:  5,
)->get();

Article::knn(
    field:      'embedding',
    vector:     [0.1, 0.2, ...],
    k:          10,
    candidates: 100,
    filter:     ['term' => ['status' => ['value' => 'published']]],
)->get();

use Elastico\Mapping\RuntimeField;
use Elastico\Mapping\FieldType;

Article::runtimeField('day_of_week', new RuntimeField(
    type:   FieldType::keyword,
    script: "emit(doc['published_at'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))",
))->get();

// Lazy collection — streams all matching docs without memory overhead
Article::where('status', 'published')->cursor()->each(function ($article) {
    // process
});

// Execute multiple queries in a single HTTP round-trip
[$published, $drafts] = $builder->getMany([
    Article::where('status', 'published'),
    Article::where('status', 'draft'),
]);

Article::where('status', 'published')->count();
Article::where('status', 'published')->sum('score');
Article::where('status', 'published')->avg('score');
Article::where('status', 'published')->min('score');
Article::where('status', 'published')->max('score');

// Inspect the Elasticsearch DSL payload
$payload = Article::where('status', 'published')->toSql();

use Elastico\Aggregations\Metric\Avg;
use Elastico\Aggregations\Metric\Sum;
use Elastico\Aggregations\Metric\Min;
use Elastico\Aggregations\Metric\Max;
use Elastico\Aggregations\Metric\Cardinality;
use Elastico\Aggregations\Metric\ValueCount;
use Elastico\Aggregations\Metric\Stats;
use Elastico\Aggregations\Metric\Percentiles;
use Elastico\Aggregations\Metric\TopHits;

$results = Article::where('status', 'published')
    ->addAggregation('avg_score',   new Avg('score'))
    ->addAggregation('total_views', new Sum('views'))
    ->addAggregation('authors',     new Cardinality('author_id'))
    ->limit(0)  // set to 0 if you only need aggregation results
    ->get();

$avgScore   = $results->aggregation('avg_score')->value();
$totalViews = $results->aggregation('total_views')->value();
$authCount  = $results->aggregation('authors')->value();

use Elastico\Aggregations\Bucket\Terms;
use Elastico\Aggregations\Bucket\DateHistogram;
use Elastico\Aggregations\Bucket\Histogram;
use Elastico\Aggregations\Bucket\Range;
use Elastico\Aggregations\Bucket\Filter;
use Elastico\Aggregations\Bucket\Nested;

$results = Article::addAggregation(
    'by_status',
    new Terms('status', size: 10)
)->limit(0)->get();

foreach ($results->aggregation('by_status')->buckets() as $bucket) {
    echo "{$bucket['key']}: {$bucket['doc_count']}\n";
}

$byStatus = (new Terms('status', size: 10))
    ->addAggregation('avg_score', new Avg('score'));

$results = Article::addAggregation('by_status', $byStatus)->limit(0)->get();

foreach ($results->aggregation('by_status')->buckets() as $bucket) {
    $avg = $bucket->aggregation('avg_score')->value();
}

use Elastico\Scripting\Increment;

$article->update(new Increment(field: 'views', amount: 1));

// With additional fields to set alongside
$article->update(new Increment(field: 'views', amount: 1, extra: ['last_viewed_at' => now()]));

// Decrement
Article::where('status', 'active')->decrement('priority', 5);

use Elastico\Scripting\UpdateParams;

$article->update(
    (new UpdateParams(['multiplier' => 2]))
        ->withModel(['score' => 100])  // merges with model fields
);

$results = Article::addAggregation('by_status', new Terms('status'))
    ->postWhere('status', 'published')  // filters hits but not aggs
    ->get();

use Elastico\ILM\Policy;
use Elastico\ILM\Phases\HotPhase;
use Elastico\ILM\Phases\WarmPhase;
use Elastico\ILM\Phases\DeletePhase;
use Elastico\ILM\Actions\RolloverAction;
use Elastico\ILM\Actions\ReadOnlyAction;
use Elastico\ILM\Actions\DeleteAction;
use Elastico\ILM\Actions\ForceMergeAction;

$policy = new Policy(
    id: 'articles-policy',
    hot_phase: new HotPhase(
        min_age: '0ms',
        rollover: new RolloverAction(max_age: '7d', max_size: '50gb'),
    ),
    warm_phase: new WarmPhase(
        min_age: '7d',
        read_only: new ReadOnlyAction(),
        force_merge: new ForceMergeAction(max_num_segments: 1),
    ),
    delete_phase: new DeletePhase(
        min_age: '90d',
        delete: new DeleteAction(),
    ),
);

class Article extends Model
{
    // Elasticsearch-to-Elasticsearch
    public function comments(): HasMany
    {
        return $this->hasMany(Comment::class, 'article_id');
    }

    // Embedded documents
    public function metadata(): EmbedsOne
    {
        return $this->embedsOne(ArticleMetadata::class);
    }

    // Hybrid: Elasticsearch model → SQL model
    public function author(): BelongsTo
    {
        return $this->belongsTo(\App\Models\User::class, 'author_id');
    }
}
bash
php artisan elastic:index:create "App\Models\Article"
php artisan elastic:index:create "App\Models\Article" --fresh   # drop & recreate
php artisan elastic:index:delete "App\Models\Article"