Here’s an optimized version of your document:
QueryAdapter is a powerful Laravel package that provides an intuitive abstraction layer for interacting with Elasticsearch indices. It includes a set of query builders designed for searching, aggregating, and suggesting data, while offering essential utilities for efficient index management. This package enables developers to work with Elasticsearch in a structured and efficient way, eliminating the complexity of low-level queries.
To get started, install the package via Composer:
composer require opsource/query-adapter
Before using the QueryAdapter package, ensure that your Elasticsearch client is properly configured. The package relies on ElasticClient
to manage all Elasticsearch communications, ensuring smooth data indexing and retrieval.
The InteractsWithIndex
trait offers powerful methods to manage and query Elasticsearch indices efficiently.
Insert multiple documents into an Elasticsearch index in a single operation for improved performance:
$data = [
['index' => ['_id' => 1]],
['name' => 'Product A', 'price' => 100],
['index' => ['_id' => 2]],
['name' => 'Product B', 'price' => 200],
];
$result = $this->bulk($data);
Retrieve detailed information about a specific index, including settings and mappings:
$indexInfo = $this->catIndices('my_index');
Remove an index when it is no longer needed:
$result = $this->indicesDelete('my_index');
Define and create a new Elasticsearch index with custom settings:
$settings = [
'settings' => [
'number_of_shards' => 1,
'number_of_replicas' => 1
]
];
$result = $this->indicesIndex('my_new_index', $settings);
Make recent operations visible to search queries:
$result = $this->indicesRefresh();
QueryAdapter simplifies querying with its builder-based approach.
Perform a basic search query:
$query = $this->query()->match('name', 'Product A')->get();
Create an index class similar to an Eloquent model:
use Ensi\LaravelElasticQuery\ElasticIndex;
class ProductsIndex extends ElasticIndex
{
protected string $name = 'test_products';
protected string $indicator = 'product_id';
}
Set a unique document attribute name for $indicator
, which is used as an additional sort in search_after
.
Perform a search with complex filters and sorting:
$searchQuery = ProductsIndex::queryEngine();
$hits = $searchQuery
->where('rating', '>=', 5)
->whereDoesntHave('offers', fn(BoolQuery $queryEngine) => $queryEngine->where('seller_id', 10)->where('active', false))
->sortBy('rating', 'desc')
->sortByNested('offers', fn(SortableQuery $queryEngine) => $queryEngine->where('active', true)->sortBy('price', mode: 'min'))
->take(25)
->get();
$searchQuery->where('field', 'value');
$searchQuery->where('field', '>', 'value'); // Operators: `=`, `!=`, `>`, `<`, `>=`, `<=`
$searchQuery->whereNot('field', 'value'); // Equivalent to `where('field', '!=', 'value')`
$searchQuery->whereIn('field', ['value1', 'value2']);
$searchQuery->whereNotIn('field', ['value1', 'value2']);
$searchQuery->whereNull('field');
$searchQuery->whereNotNull('field');
$searchQuery->whereHas('nested_field', fn(BoolQuery $subQuery) => $subQuery->where('field_in_nested', 'value'));
$searchQuery->whereDoesntHave('nested_field', function (BoolQuery $subQuery) {
$subQuery->whereHas('nested_field', fn(BoolQuery $subQuery2) => $subQuery2->whereNot('field', 'value'));
});
nested_field
must have nested
type. Subqueries can only use subdocument fields.
$searchQuery->whereMatch('field_one', 'queryEngine string');
$searchQuery->whereMultiMatch(['field_one^3', 'field_two'], 'queryEngine string', MatchType::MOST_FIELDS);
$searchQuery->sortBy('field', SortOrder::DESC, SortMode::MAX, MissingValuesMode::FIRST);
$searchQuery->sortByNested('nested_field', fn(SortableQuery $subQuery) => $subQuery->where('field_in_nested', 'value')->sortBy('field'));
Use dedicated sort methods for each sort type:
$searchQuery->minSortBy('field', 'asc');
$searchQuery->maxSortBy('field', 'asc');
$searchQuery->avgSortBy('field', 'asc');
$searchQuery->sumSortBy('field', 'asc');
$searchQuery->medianSortBy('field', 'asc');
$page = $searchQuery->paginate(15, 45);
$page = $searchQuery->cursorPaginate(10);
$pageNext = $searchQuery->cursorPaginate(10, $page->next);
Create aggregation queries:
$aggQuery = ProductsIndex::aggregate();
$aggs = $aggQuery
->where('active', true)
->terms('codes', 'code')
->count('product_count', 'product_id')
->nested(
'offers',
fn(AggregationsBuilder $builder) => $builder->where('seller_id', 10)->minmax('price', 'price')
);
$aggQuery->terms('agg_name', 'field', 25);
$aggQuery->minmax('agg_name', 'field');
$aggQuery->count('agg_name', 'field');
Create suggest queries for autocomplete or typo correction:
$sugQuery = ProductsIndex::suggest();
$suggests = $sugQuery->phrase('suggestName', 'name.trigram')->text('glves')->size(1)->shardSize(3)->get();
Term Suggester:
$aggQuery->term('suggestName', 'name.trigram')->text('glves')->get();
Phrase Suggester:
$aggQuery->phrase('suggestName', 'name.trigram')->text('glves')->get();
Generates various engine components:
php artisan engine:make {type} [--model=] [--module=] [--index=] [--force] [--facade] [--job]
Generates a facade for a search engine model.
Creates a directive class for a search engine model.
Enable query logging to track executed queries:
ElasticQuery::enableQueryLog();
$records = ElasticQuery::getQueryLog();
ElasticQuery::disableQueryLog();
Configure the following environment variables:
ELASTICSEARCH_HOSTS=https://localhost:9200
ELASTICSEARCH_RETRIES=2
ELASTICSEARCH_USERNAME=admin
ELASTICSEARCH_PASSWORD=admin
ELASTICSEARCH_SSL_VERIFICATION=true
Separate releases are created for Elasticsearch 7 and 8. Development for each version occurs in corresponding branches.
See CONTRIBUTING for details.
MIT License. See LICENSE.md for more information.
This version improves readability and structure while maintaining clarity. It consolidates sections, removes redundancy, and ensures consistency throughout the document.