2.2.0
Global update
- New Query API
- More efficient result sorting using SearchQuery
- Ability to sort aggregation results
- Performance improvements
- Index optimization using
$searchIndex->optimize()
- FilterInterface changed
New Query API
<?php
use KSamuel\FacetedSearch\Index\ArrayIndex;
use KSamuel\FacetedSearch\Search;
use KSamuel\FacetedSearch\Query\SearchQuery;
use KSamuel\FacetedSearch\Query\AggregationQuery;
use KSamuel\FacetedSearch\Query\Order;
use KSamuel\FacetedSearch\Filter\ValueFilter;
// load index
$searchIndex = new ArrayIndex();
$searchIndex->setData($someIndexData);
// create search instance
$search = new Search($searchIndex);
// Find results
$query = (new SearchQuery())
->filters([
new ValueFilter('color', ['black','white']),
new ValueFilter('size', [41,42])
])
// It is possible to set List of record id to search in.
// For example list of records id that found by external FullText search.
->inRecords([1,2,3,19,17,21/*..some input record ids..*/])
// Now results can be sorted by field value.
// Note! If result item has not such field then item will be excluded from results
->order('price', Order::SORT_DESC);
$results = $search->query(query);
// Find Acceptable filters for user selected input
$query = (new AggregationQuery())
->filters([
new ValueFilter('color', ['black','white']),
new ValueFilter('size', [41,42])
])
// Count items for each acceptable filter value (slower)
->countItems()
// Sort results by fields and values
->sort();
$results = $search->aggregate(query);
New aggregation API has changed result format for $search->aggregate()
With countItems:
[
'field1' => [
'value1' => 10,
'value2' => 20
]
]
Without countItems:
[
'field1' => [
'value1' => true,
'value2' => true
]
]
The change was necessary to unify the results structure.
Old API produces results as before in slightly different formats for:
$search->findAcceptableFilters();
$search->findAcceptableFiltersCount();
Backward compatibility
The version is fully backward compatible if you haven't used own filters implementations.
The old API format is available but marked as deprecated.
FilterInterface changed. You need to take this into account if you implemented your own versions of filters
//Interface
use KSamuel\FacetedSearch\Filter\FilterInterface;
//changed
public function filterResults(array $facetedData, ?array $inputIdKeys = null): array;
//replaced with
public function filterInput(array $facetedData, array &$inputIdKeys): void;
Performance
Added index optimization method.
<?php
use KSamuel\FacetedSearch\Index\ArrayIndex;
$searchIndex = new ArrayIndex();
/*
* Getting products data from DB
*/
$data = [
['id'=>7, 'color'=>'black', 'price'=>100, 'sale'=>true, 'size'=>36],
// ....
];
foreach($data as $item){
$recordId = $item['id'];
// no need to add faceted index by id
unset($item['id']);
$searchIndex->addRecord($recordId, $item);
}
// You can optionally call index optimization before using (since v2.2.0).
// The procedure can be run once after changing the index data.
// Optimization takes a few seconds, you should not call it during the processing of user requests.
$searchIndex->optimize();
// save index data to some storage
$indexData = $searchIndex->getData();
// We will use file for example
file_put_contents('./first-index.json', json_encode($indexData));
Unbalanced Dataset added to Benchmark test
v2.2.0 Bench ArrayIndex PHP 8.2 + JIT + opcache (no xdebug extension)
Items count | Memory | Find | Get Filters (aggregate) | Get Filters & Count (aggregate) | Sort by field | Results Found |
---|---|---|---|---|---|---|
10,000 | ~3Mb | ~0.0004 s. | ~0.001 s. | ~0.002 s. | ~0.0001 s. | 907 |
50,000 | ~20Mb | ~0.001 s. | ~0.005 s. | ~0.010 s. | ~0.0004 s. | 4550 |
100,000 | ~40Mb | ~0.003 s. | ~0.013 s. | ~0.023 s. | ~0.0009 s. | 8817 |
300,000 | ~95Mb | ~0.009 s. | ~0.034 s. | ~0.077 s | ~0.003 s. | 26891 |
1,000,000 | ~329Mb | ~0.039 s. | ~0.131 s. | ~0.281 s. | ~0.014 s. | 90520 |
1,000,000 UB | ~324Mb | ~0.099 s. | ~0.218 s. | ~0.401 s. | ~0.028 s. | 179856 |
v2.2.0 Bench FixedArrayIndex PHP 8.2 + JIT + opcache (no xdebug extension)
Items count | Memory | Find | Get Filters (aggregate) | Get Filters & Count (aggregate) | Sort by field | Results Found |
---|---|---|---|---|---|---|
10,000 | ~2Mb | ~0.0007 s. | ~0.001 s. | ~0.003 s. | ~0.0002 s. | 907 |
50,000 | ~12Mb | ~0.003 s. | ~0.007 s. | ~0.017 s. | ~0.0009 s. | 4550 |
100,000 | ~23Mb | ~0.006 s. | ~0.017 s. | ~0.039 s. | ~0.001 s. | 8817 |
300,000 | ~70Mb | ~0.020 s. | ~0.056 s. | ~0.120 s. | ~0.005 s. | 26891 |
1,000,000 | ~233Mb | ~0.073 s. | ~0.207 s. | ~0.447 s. | ~0.021 s. | 90520 |
1,000,000 UB | ~233Mb | ~0.162 s. | ~0.271 s. | ~0.609 s. | ~0.035 s. | 179856 |
Previous version
v2.1.5 Bench ArrayIndex PHP 8.2 + JIT + opcache (no xdebug extension)
Items count | Memory | Find | Get Filters (aggregate) | Get Filters & Count (aggregate) | Sort by field | Results Found |
---|---|---|---|---|---|---|
10,000 | ~3Mb | ~0.0004 s. | ~0.001 s. | ~0.002 s. | ~0.0001 s. | 907 |
50,000 | ~20Mb | ~0.001 s. | ~0.006 s. | ~0.011 s. | ~0.0005 s. | 4550 |
100,000 | ~40Mb | ~0.003 s. | ~0.014 s. | ~0.024 s. | ~0.001 s. | 8817 |
300,000 | ~95Mb | ~0.010 s. | ~0.042 s. | ~0.082 s | ~0.003 s. | 26891 |
1,000,000 | ~329Mb | ~0.046 s. | ~0.164 s. | ~0.306 s. | ~0.015 s. | 90520 |
1,000,000 UB | ~324Mb | ~0.102 s. | ~0.238 s. | ~0.446 s. | ~0.031 s. | 179856 |
v2.1.5 Bench FixedArrayIndex PHP 8.2 + JIT + opcache (no xdebug extension)
Items count | Memory | Find | Get Filters (aggregate) | Get Filters & Count (aggregate) | Sort by field | Results Found |
---|---|---|---|---|---|---|
10,000 | ~2Mb | ~0.0006 s. | ~0.001 s. | ~0.003 s. | ~0.0002 s. | 907 |
50,000 | ~12Mb | ~0.003 s. | ~0.007 s. | ~0.017 s. | ~0.0009 s. | 4550 |
100,000 | ~23Mb | ~0.006 s. | ~0.017 s. | ~0.040 s. | ~0.001 s. | 8817 |
300,000 | ~70Mb | ~0.019 s. | ~0.056 s. | ~0.120 s. | ~0.006 s. | 26891 |
1,000,000 | ~233Mb | ~0.077 s. | ~0.202 s. | ~0.455 s. | ~0.023 s. | 90520 |
1,000,000 UB | ~233Mb | ~0.146 s. | ~0.292 s. | ~0.586 s. | ~0.044 s. | 179856 |