The Search API support for OR facets is a really nice feature that would not appear if people are using the DB backend for evaluation.

Implementing this requires us to build a different base query for each OR facet, in which the filters for this facet are removed.

Comments

damien tournoud’s picture

Status: Active » Needs review
StatusFileSize
new2.66 KB
damien tournoud’s picture

StatusFileSize
new2.94 KB

Same patch with an additional exception thrown if the facet operator is unknown.

evanbarter’s picture

Status: Needs review » Needs work

I've tried this patch and the dependency and found that they both apply cleanly, however I'm running in to an issue which might just be my understanding but perhaps not.

Currently I'm trying this on a View (of commerce products) with 3 facets (color, manufacturer, type), each of which is set up as an 'or' thanks to this patch. The goal was a "free form" list of products which should never return an empty set. For example, if I select the colours "red" and "blue", ideally the manufacturers facet options should be reduced to the manufacturers that offer red and blue products (and similarly for type). If I then select "manufacturer A" and "manufacturer B" the type facet options should be reduced to types of products which are offered by "manufacturer A" or "manufacturer B" and are "red" or "blue".

The behaviour I'm seeing at the moment is if I select the colours "red" and "blue", there are type options that aren't removed from the facet options, even though there are no "red" or "blue" products with that type, thus it's possible to get to an empty result.

If this doesn't make sense please let me know I'll try and get in touch with you on IRC with an example site. I'm setting this to needs work but if my understanding of how this should work is wrong please set it back and I'll do my best to give it a proper review. Thanks!

evanbarter’s picture

Just saw http://drupal.org/node/1204966#comment-5417670 which I guess could be related?

jax’s picture

restyler’s picture

is this supposed to be working with FacetAPI?
I get "operator not defined" error all the time, since there is no $facet['operator'] at all.

restyler’s picture

okay, I see it uses FacetAPI constants :) how can I define "operator" element in facet array?

drunken monkey’s picture

Status: Needs work » Postponed

I'll postpone this now, until we commit #1390598: Add a way to easily identify facet filters inside the query.
I'll also take a closer look at the patch then, I've now just skimmed over it.

Thanks, in any case!

pacufist’s picture

Bug in #2 patch.

Need handle clone somehow. Now this code, doesn't clone filters of the object.

$or_query = clone $query;

As result we looses filters in $query after unset it in $or_query

unset($filters[$filter_id]);

pacufist’s picture

StatusFileSize
new537 bytes

Fast patch. Extended class SearchApiQuery with __clone() function.

pacufist’s picture

Also $fields initialization missed after patch. This part was moved to function buildDatabaseQuery :

        $index = $query->getIndex();
        if (empty($this->options['indexes'][$index->machine_name])) {
            throw new SearchApiException(t('Unknown index @id.', array('@id' => $index->machine_name)));
        }
        $fields = $this->options['indexes'][$index->machine_name];

But due the fact that this array used in next part of code, we need initialize $fields in function search() as well.

                    if (!isset($fields[$field_name])) {
                        throw new SearchApiException(t('Trying to sort on unknown field @field.', array('@field' => $field_name)));
                    }
yaelsho’s picture

Hello,
Is there any news regarding this issue? bit confused from the patch parts mentioned above.
If there is a patch file that worked for you, I'll be happy to test it.
Thanks, Yael

farez’s picture

Echoing yaelsho... any news on this one? Is "OR" supported now for DB search?

irowboat’s picture

Same question as the previous askers - any updates on this issue? Thanks.

drunken monkey’s picture

Title: Implement support for search_api_facets_operator_or » Add support for OR facets
Issue summary: View changes
Status: Postponed » Needs review
StatusFileSize
new4.72 KB

Sorry for leaving this lying here for so long, it was high up on my TODO list, I've just got very little time for such larger feature requests. But I'm sure we can now get this committed in the coming weeks!

I've moved the cloning problem to a new issue (since it has to be handled in the Search API itself anyways) and provided a complete patch there: #2144531: Fix cloning of queries to clone filters, too.

Regarding the patch by Damien itself, that already works and looks brilliantly, thanks a lot again! It of course needed a re-roll, but other than that there was only one tiny mistake (the operator key for facets is optional). I also added some tests, and I think we should now be all set.
Please test/review!

Status: Needs review » Needs work

The last submitted patch, 15: 1390586-15--or_facets.patch, failed testing.

The last submitted patch, 15: 1390586-15--or_facets.patch, failed testing.

drunken monkey’s picture

Ah. Yes. Of course. We'll have to wait (at least) for Search API 1.10 to be released before we can commit this. We maybe should add a versioned dependency there, too. On the other hand, the error is only triggered when using OR facets, so maybe documenting this is enough.

drunken monkey’s picture

Status: Needs work » Needs review

So, does anyone want to test or review this?
(Will let the test bot test in a few days.)

The last submitted patch, 10: search_api_query_clone_filters.patch, failed testing.

The last submitted patch, 2: 1390586-search-api-db-or-facets.patch, failed testing.

The last submitted patch, 1: 1390586-search-api-db-or-facets.patch, failed testing.

antonnavi’s picture

StatusFileSize
new3.31 KB

Here is my implementation of Search API DB module OR logic (inside 1 facet).
It's based on posted patches adapted to last module version + additional logic for handling "No results" case and display all facets (have ability unselect it).
Patch required current latest Search API (7.x-1.10) and Search API DB (7.x-1.1) modules version.
Sponsored by Skilld

Status: Needs review » Needs work

The last submitted patch, 23: search_api_db_or_logic.patch, failed testing.

The last submitted patch, 23: search_api_db_or_logic.patch, failed testing.

antonnavi’s picture

Status: Needs work » Needs review
StatusFileSize
new3.25 KB

Fixed path to patched file.

Status: Needs review » Needs work

The last submitted patch, 26: search_api_db_or_logic.patch, failed testing.

antonnavi’s picture

StatusFileSize
new3.28 KB

Using facet operator exceptions fixed.

antonnavi’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 28: search_api_db_or_logic.patch, failed testing.

antonnavi’s picture

Status: Needs work » Needs review
StatusFileSize
new3.28 KB

Patch format fixed.

andypost’s picture

  1. +++ b/search_api_db.test
    @@ -45,6 +45,7 @@ class SearchApiDbTest extends DrupalWebTestCase {
    +    $this->checkFacets();
    
    @@ -237,6 +238,56 @@ class SearchApiDbTest extends DrupalWebTestCase {
    +  protected function checkFacets() {
    +    $query = $this->buildSearch();
    

    Anton, you forget to add test for patch

  2. +++ b/service.inc
    @@ -1482,7 +1483,24 @@ class SearchApiDbService extends SearchApiAbstractService {
    +      if (empty($facet['operator']) || $facet['operator'] != 'or') {
    +        // All the AND facets can use the main query.
    

    do we really need to skip throwing excepion in case od unknown operator?

  3. +++ b/service.inc
    @@ -1482,7 +1483,24 @@ class SearchApiDbService extends SearchApiAbstractService {
    +        $tag = 'facet:' . $facet['field'];
    ...
    +          if ($filter instanceof SearchApiQueryFilterInterface && $filter->hasTag($tag)) {
    +            unset($filters[$filter_id]);
    

    do tags enough to unset?

Anton's patch review

  1. +++ b/service.inc
    @@ -992,6 +993,11 @@ class SearchApiDbService extends SearchApiAbstractService {
    +      // Display facets with selected items if no refults found.
    +      if ($query->getOption('search_api_facets')) {
    +        $query->noResultsFound = TRUE;
    +        $results['search_api_facets'] = $this->getFacets($query, clone $db_query);
    

    is this change related?

  2. +++ b/service.inc
    @@ -1560,7 +1566,52 @@ class SearchApiDbService extends SearchApiAbstractService {
    +                // If no results found - remove all filters from facet query
    +                // for "see" all selected facets and has ability "uncheck" it.
    +                if (isset($query->noResultsFound)) {
    +                  if (isset($filters[$filter_id])) {
    +                    unset($filters[$filter_id]);
    

    this could be moved out of internal loop

  3. +++ b/service.inc
    @@ -1560,7 +1566,52 @@ class SearchApiDbService extends SearchApiAbstractService {
    +                  if (in_array($facet['field'], $filter_items)) {
    +                    unset($filters[$filter_id]);
    

    loops is not needed here

antonnavi’s picture

StatusFileSize
new6.77 KB

1.1 Anton, you forget to add test for patch
-> Patch was updated and now it is combination of previous version + 1390586-15--or_facets.patch

2.1 is this change related?
-> This change related because it handle "No results" case and help "end user": Give ability uncheck incorrect facet items and not lose already selected filters. This part was reworked on current patch.

2.2 this could be moved out of internal loop
-> Fixed.

2.3 loops is not needed here
-> Fixed.

Status: Needs review » Needs work

The last submitted patch, 33: search_api_db_or_logic.patch, failed testing.

antonnavi’s picture

Status: Needs work » Needs review
StatusFileSize
new7.3 KB

Fixed test error.

antonnavi’s picture

StatusFileSize
new6.81 KB

Fixed path to patched files.

The last submitted patch, 35: search_api_db_or_logic.patch, failed testing.

andypost’s picture

Status: Needs review » Reviewed & tested by the community
StatusFileSize
new621 bytes
new7.01 KB

And let's get rid of drupal_map_assoc() as well

drunken monkey’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new4.73 KB

@ Antonnavi, andypost: Thanks a lot for your work on this!
However, Antonnavi's additional change is definitely not in the scope of this issue! Please create a new one for that, elaborate on your reasoning and amend the patch with a server option to turn this behavior on and off.

As all other changes were, I think, only related to the new code, a re-roll of my patch in #15 should be OK, right? (I actually found a bug in one of the new tests, maybe that was the cause of the previous fails.)
Please find it attached and see if it works for you, or you find anything wrong with it. Then I can hopefully finally commit this.

antonnavi’s picture

Status: Needs review » Reviewed & tested by the community

Last added patch #39 works fine for me.
New issue No facets on no results was created (with detailed description and patch for fix it).

drunken monkey’s picture

Status: Reviewed & tested by the community » Fixed

OK, great to hear!
Committed.
Thanks a lot again to everyone who worked on this – especially, of course, to Damien!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.