spatie/elasticsearch-query-builder
A lightweight, fluent PHP API for building and executing ElasticSearch queries. Chain queries and aggregations, then call search(). Built for Spatie's search-string-parser but flexible enough to cover most common use cases.
Architecture fit
elasticsearch/elasticsearch PHP client (Elastic\Elasticsearch\Client). It is not a Laravel package: no service provider, no config file, no facade, no Eloquent/Scout integration. Treat it as a library, not a Laravel module.spatie/elasticsearch-search-string-parser. That means the query-type coverage is driven by Spatie's own use cases (match, multi-match, term(s), bool, nested, range, geo-shape, regexp, wildcard, percolate, collapse, inner hits, plus a broad aggregation set). Anything outside that surface requires either a PR or the raw payload escape hatch.getPayload() method is the architectural release valve: teams can build 80–90% of a query fluently and inject hand-written DSL fragments for the remainder without abandoning the abstraction. This materially lowers the "abstraction traps you" risk.Integration feasibility
composer require spatie/elasticsearch-query-builder, instantiate Builder with a client, call search(). No migrations, no schema, no DI wiring beyond binding the client in the container.elasticsearch/elasticsearch v7). Verify the matrix against your actual ES server version and PHP client major before adopting.Technical risk
Key questions
search_after, point-in-time, collapse + inner hits)? Which of these are absent, and are we prepared to submit PRs versus fall back to getPayload()?Stack fit
SearchRepository / SearchService) so that Builder, Query objects, and raw responses do not leak into controllers or domain models.Elastic\Elasticsearch\Client → cluster. The domain service is the seam that lets you swap or fork the package later.Migration path
getPayload() makes this diffable without executing searches.RawQuery wrapper or a getPayload() post-processing hook) so that gaps never block delivery.Compatibility
elasticsearch/elasticsearch major ↔ spatie/elasticsearch-query-builder major. Lock all three in composer.json and in the deployment image.FilterAggregation with nested sub-aggregations, percolate behavior changes, collapse semantics) should be validated against the target cluster version, not just against the package's test suite.NestedQuery::create(...) accepts a Query instance rather than only a static factory — confirm constructor vs. create() usage in the version you pin, as the README shows both forms.Sequencing
must_not, nested with inner hits, terms aggregation, collapse). Measure how much raw DSL is still required.Maintenance
Support
Scaling
addQuery() mutates state.from/size; deep pagination (search_after, point-in-time) is likely out of scope and should be evaluated against the roadmap question above.Failure modes
getPayload(). Teams must build that into their debugging runbook from day one.Ramp-up
create() factories and named arguments. A PHP developer familiar with ES can be productive in hours.match vs term on an analyzed field, must vs filter affecting scoring and caching). Onboarding must include a short DSL literacy component, not just package API documentation.How can I help you explore Laravel packages today?