Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
k-samuel committed May 21, 2021
2 parents 74bd730 + 82db06b commit 9ea782c
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 11 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ $records = $search->find($filters);
// It can be used for updating client UI.
$filterData = $search->findAcceptableFilters($filters);

// If you want to get acceptable filters values with items count use findAcceptableFiltersCount
// note that filters is not applied for itself for counting
// values count of a particular field depends only on filters imposed on other fields
$filterData = $search->findAcceptableFiltersCount($filters);


// If $filters is an empty array [], all acceptable values will be returned
$filterData = $search->findAcceptableFilters([]);

Expand Down
3 changes: 3 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

### v1.2.5 (21.05.2021)
* findAcceptableFiltersCount method added, return acceptable filters with values count

### v1.2.4 (12.05.2021)
* Result Sorter added
* Performance test refactoring
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "k-samuel/faceted-search",
"version": "1.2.4",
"version": "1.2.5",
"type": "library",
"description": "PHP Faceted search",
"keywords": ["php","faceted search"],
Expand Down
43 changes: 36 additions & 7 deletions src/Search.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,13 @@ public function find(array $filters, ?array $inputRecords = null) : array
}
return array_values($result);
}

/**
* Find acceptable filter values
* @param array<FilterInterface> $filters
* @param array<int> $inputRecords
* @return array<array>
*/
public function findAcceptableFilters(array $filters = [], array $inputRecords = []): array
private function findFilters(array $filters = [], array $inputRecords = [], bool $countValues = false) : array
{
$result = [];
$facetsData = $this->index->getData();
Expand All @@ -108,11 +107,13 @@ public function findAcceptableFilters(array $filters = [], array $inputRecords =
if(!empty($filters)){
// index filters by field
foreach ($filters as $filter){
/** @var FilterInterface $filter */
/**
* @var FilterInterface $filter
*/
$indexedFilters[$filter->getFieldName()] = $filter;
}
}
$count = 0;

foreach ($facetsData as $filterName => $filterValues) {
if(empty($indexedFilters) && empty($inputRecords)){
$result[$filterName] = array_keys($filterValues);
Expand All @@ -125,13 +126,41 @@ public function findAcceptableFilters(array $filters = [], array $inputRecords =
$recordIds = array_flip($recordIds);
}
foreach ($filterValues as $filterValue => $data) {
$count++;
if (!empty(array_intersect_key($data, $recordIds))) {
$result[$filterName][] = $filterValue;
// need to count values
if($countValues){
$intersect = array_intersect_key($data, $recordIds);
if(!empty($intersect)){
$result[$filterName][$filterValue] = count($intersect);
}
}else{
if(!empty(array_intersect_key($data, $recordIds))) {
$result[$filterName][] = $filterValue;
}
}
}
}
}
return $result;
}
/**
* Find acceptable filter values
* @param array<FilterInterface> $filters
* @param array<int> $inputRecords
* @return array<array>
*/
public function findAcceptableFilters(array $filters = [], array $inputRecords = []): array
{
return $this->findFilters($filters, $inputRecords, false);
}

/**
* Find acceptable filters with values count
* @param array<FilterInterface> $filters
* @param array<int> $inputRecords
* @return array<array>
*/
public function findAcceptableFiltersCount(array $filters = [], array $inputRecords = []): array
{
return $this->findFilters($filters, $inputRecords, true);
}
}
8 changes: 5 additions & 3 deletions tests/performance/find.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@

//test acceptable
$t = microtime(true);
$filters = $search->findAcceptableFilters($filters);

$filtersData = $search->findAcceptableFilters($filters);
echo 'Filters: ' . count($filters) . "\t\t" . (microtime(true) - $t) . "s" . PHP_EOL;


//test acceptable with count
$t = microtime(true);
$filtersData = $search->findAcceptableFiltersCount($filters);
echo 'Filters with count: ' . count($filters) . "\t" . (microtime(true) - $t) . "s" . PHP_EOL;
72 changes: 72 additions & 0 deletions tests/unit/SearchTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,78 @@ public function testGetAcceptableFilters()
}
}

public function testGetAcceptableFiltersCount()
{
$records = $this->getTestData();
$index = new Index();
foreach ($records as $id=>$item){
$index->addRecord($id, $item);
}
$facets = new Search($index);
$filter = new ValueFilter('color' ,'black');

$acceptableFilters = $facets->findAcceptableFiltersCount([$filter]);

$expect = [
'vendor' => ['Apple'=>1,'Samsung'=>2,'Xiaomi'=>1],
'model' => ['Iphone X Pro Max'=>1,'Galaxy S20'=>1, 'Galaxy A5'=>1, 'MI 9'=>1],
'price' => [80999=>1, 70599=>1, 15000=>1, 26000=>1],
// self filtering is not using by facets logic
'color' => ['black'=>4,'white'=>1,'yellow'=>1],
'has_phones' => [1=>4],
'cam_mp' => [40=>1, 105=>1, 12=>1, 48=>1],
'sale' => [1=>3,0=>1]
];
foreach($expect as $field=>&$values){
asort($values);
}unset($values);
foreach($acceptableFilters as $field=>&$values){
asort($values);
}unset($values);

foreach ($expect as $filter => $values){
$this->assertArrayHasKey($filter, $acceptableFilters);
$this->assertEquals($values, $acceptableFilters[$filter]);
}
}

public function testGetAcceptableFiltersCountMulty()
{
$records = [
['color'=>'black', 'size'=>7, 'group'=>'A'],
['color'=>'black', 'size'=>8, 'group'=>'A'],
['color'=>'white', 'size'=>7, 'group'=>'B'],
['color'=>'yellow', 'size'=>7, 'group'=>'C'],
['color'=>'black', 'size'=>7, 'group'=>'C'],
];
$index = new Index();
foreach ($records as $id=>$item){
$index->addRecord($id, $item);
}
$facets = new Search($index);
$filter = new ValueFilter('color' ,'black');
$filter2 = new ValueFilter('size' ,7);

$acceptableFilters = $facets->findAcceptableFiltersCount([$filter, $filter2]);

$expect = [
'color' => ['black'=>2,'white'=>1,'yellow'=>1],
'size' => [7=>2,8=>1],
'group' => ['A'=>1,'C'=>1],
];
foreach($expect as $field=>&$values){
asort($values);
}unset($values);
foreach($acceptableFilters as $field=>&$values){
asort($values);
}unset($values);

foreach ($expect as $filter => $values){
$this->assertArrayHasKey($filter, $acceptableFilters);
$this->assertEquals($values, $acceptableFilters[$filter]);
}
}

public function getTestData() : array
{
return [
Expand Down

0 comments on commit 9ea782c

Please sign in to comment.