Created a new facetapi widget, and was having difficulty understanding why I was getting an odd facet count under certain circumstances, assumed it was my new facetapi widget but the issue seems to be with (query_type_term.inc) under /search_api/contrib/search_api_facetapi/plugins/facetapi/.
Example (Minimum facet count set to 1) :
Cars with the facets (Makes / Models)
Makes (Facet set to OR):
--Vauxhall (10)
--Audi (10)
Models (Facet set to OR)
--A3 (10)
--Insignia (10)
Steps:
1. User selects from Makes - Vauxhall and Audi.
2. 20 results are returned, and the Models facet displays all filters available (A3 and Insignia)
3. User selects Insignia
4. 10 Results are returned, awesome, but here's where the issue comes in, the `Makes` facet count is now incorrect as both Vauxhall and Audi have a facet count of 10. Where the actual result should be Vauxhall(10), Audi(0), from what I can understand this is owed to the following:
(From /search_api/contrib/search_api_facetapi/plugins/facetapi/query_type_term.inc)
<?php
// Always include the active facet items.
foreach ($this->adapter->getActiveItems($this->facet) as $filter) {
$build[$filter['value']]['#count'] = $results['result count'];
}
// Then, add the facets returned by the server.
if (isset($results['search_api_facets']) && isset($results['search_api_facets'][$this->facet['name']])) {
$values = $results['search_api_facets'][$this->facet['name']];
foreach ($values as $value) {
$filter = $value['filter'];
// As Facet API isn't really suited for our native facet filter
// representations, convert the format here. (The missing facet can
// stay the same.)
if ($filter[0] == '"') {
$filter = substr($filter, 1, -1);
}
elseif ($filter != '!') {
// This is a range filter.
$filter = substr($filter, 1, -1);
$pos = strpos($filter, ' ');
if ($pos !== FALSE) {
$filter = '[' . substr($filter, 0, $pos) . ' TO ' . substr($filter, $pos + 1) . ']';
}
}
$build[$filter] = array(
'#count' => $value['count'],
);
}
}
?>
As the server (Solr) only returns a facet count for Vauxhall(10), we incorrectly end up with a facet count of Audi(10) as well.
But if we alter the initial setting of active facet items, not setting it to the results count, but instead initiating it with 0, and only overwriting the #count with the data returned from Solr we get the correct result:
<?php
// Always include the active facet items.
foreach ($this->adapter->getActiveItems($this->facet) as $filter) {
$build[$filter['value']]['#count'] = 0;
}
?>
Hope the above makes sense. Please ask if I've not clarified anything, my model is actually a little more complex, but have tried to simplify for this example. Does anyone think the above change I'm making is incorrect? Should a facet count ever be set by the result count as opposed to the facet count returned by the server (solr or not)?
| Comment | File | Size | Author |
|---|---|---|---|
| #3 | 2629136-3--or_facet_correct_active_item_facet_count.patch | 720 bytes | drunken monkey |
Comments
Comment #2
deranga commentedComment #3
drunken monkeyI guess you're right, for OR facets this really doesn't make much sense. The thing is that the counts of active facets are normally never needed anyways, so that's probably what caused this to go unnoticed.
Your patch would probably be an improvement for this scenario, though still incorrect in some edge cases, and I don't think it would break anything with any backend I know of – they should already return the active facet items, except in your scenario (and the mentioned edge cases).
The attached patch implements your proposed change, please review!
(Tests/reviews from others would also be great, to ensure we're not breaking anything.)
Comment #4
deranga commentedHey, thanks for this, works as expected!
Appreciate this isn't ideal, as it won't be correct where the minimum facet count is greater than 1.
So I propose that the appropriate change would be to drop the `minimum facet count` in the query for active facets; and apply `minimum facet count` only to values that are not active.
For this to happen it would be a change to the query generated, and a change to this file to check minimum facet count before setting the facet?
If you agree that this makes sense and would be the correct approach, I can look to create the patch for the query generated, and the query_type_term.inc?
Let me know you thoughts.
Cheers
Comment #5
drunken monkeyNo, I don't think that would be necessary. All of this is really an edge case, but removing the min count from queries might decrease performance for a lot more people.
So if you're satisfied with the above patch for your use case, then let's just commit that one.
Comment #6
deranga commentedOkay sure; yeah this works for my use case.
Cheers!
Comment #8
drunken monkeyOK, good to hear.
Committed.
Thanks again!