In quite some use cases, we want/have to keep full (i.e. unfiltered) count on facet items even for active facets. How can we achieve this with facetapi?

Background:

Currently, if a facet is active (i.e. one of its facet items is active for filtering), the result count on the other facets reflects the filtering done by the active facet item. So if an inactive facet looks like this with no item being active:

United States (12)
Great Britain (25)
France (17)

The count changes if an item becomes acitve:

United States (0)
- Great Britain (25)
France (0)

While this is perfect if you allow multiple facet items to be active within one facet and you use them to drill down results, the count changing or being suddenly zero is very confusing if you have a limit of just one facet being active at a time. In such cases, when a click on another facet items lets users _switch_ from one facet item to another (deactivating the formerly selected and activating the newly selected item), you would expect the count behind a facet item to stay the same. In our example the output a users expects would be:

United States (12)
- Great Britain (25)
France (17)

If i understood it right, http://drupal.org/node/1431926#comment-5582734 suggests a method of doing this, but frankly i didn't get where actually to do what in code to achieve this.

Is the problem clearly enough outlined and understandable?
Any ideas?

Comments

cpliakas’s picture

Yes it is. If I am reading this correct, this seems to be the same use case as #1421564: Display the top level aggregate facet counts even when facets are activated. Could you confirm if this is the case or not?

danielnolde’s picture

btw. if anything on this is server/backend dependent: i'm using search api with apache solr 1.41.

danielnolde’s picture

Yep, Chris, looks like #1421564 is addressing the same problem.

cpliakas’s picture

Title: Keep full count on facet items for active facets. » Support the multi-select facet feature of Solr where the associated counts are maintained as if no contraints have been applied

Using http://drupal.org/node/1431926#comment-5582734 as a guide, the following text is pulled directly from the Solr documentation. Seems like the Solr related modules need to add a setting and pass the option to Facet API.

Tagging and excluding Filters

One can tag specific filters and exclude those filters when faceting. This is generally needed when doing multi-select faceting.

Consider the following example query with faceting:

q=mainquery&fq=status:public&fq=doctype:pdf&facet=on&facet.field=doctype

Because everything is already constrained by the filter doctype:pdf, the facet.field=doctype facet command is currently redundant and will return 0 counts for everything except doctype:pdf.

To implement a multi-select facet for doctype, a GUI may want to still display the other doctype values and their associated counts, as if the doctype:pdf constraint had not yet been applied. Example:

=== Document Type ===
  [ ] Word (42)
  [x] PDF  (96)
  [ ] Excel(11)
  [ ] HTML (63)

To return counts for doctype values that are currently not selected, tag filters that directly constrain doctype, and exclude those filters when faceting on doctype.

q=mainquery&fq=status:public&fq={!tag=dt}doctype:pdf&facet=on&facet.field={!ex=dt}doctype

cpliakas’s picture

danielnolde’s picture

hm, is it really that easy?
Consider the following basic case:
There are two facets, "category" and "country", and both theirs items should keep their count, i.e. their facet items result count should reflect the filtering constraints of each other facet, but not the current filtering contraint of their own facet.
Can this by accomplished using a single solr query with tags on the field/facets ?
I mean: Wouldn't that make the counts in the example independent of _all_ facet filtering contraints (and not just independent of the own facet's filtering contraints, viewed from the perspective of a facet item and its count)?

cpliakas’s picture

their facet items result count should reflect the filtering constraints of each other facet, but not the current filtering contraint of their own facet.

This is not clear to me. Could you elaborate with an example?

danielnolde’s picture

Forget it, because:

YESSSSS !!!! It's alive!!!! And working!
Well, not as a general FacetAPI Implementation, but the following code simulates the suggested tagging and tagged-excluding on solr queries made by search_api with search_api_solr, on all involved facets for a certain search_api index. See it as a proof of (the tagging) concept, and/or change it (module name, limiting index name etc.) and use it to solve your (anyone) problem:



/*
 * Implementes _search_api_solr_query_alter().
 *
 * Add tags to fq fields and facet.field fields to exclude each facet's
 * filtering contraints from influencing its own facet item's result counts,
 * to always keep the result counts of each facet item independent of that
 * facet's filtering.
 *
 * See http://drupal.org/node/1446824# for background information.
 */
function ri_portfolio_search_api_solr_query_alter(array &$call_args, SearchApiQueryInterface $query) {
  // Only alter queries on the portfolio index.
  if ($query->getIndex()->machine_name != 'portfolio') return;

  // Go through all facet.field(s).
  foreach($call_args['params']['facet.field'] as $key => $facetfield) {
    // Come up with tag name for the facet.field.
    $tag = 'dtex'.$key;
    // Mark the tag form "exclude from counting" for this facet.
    $call_args['params']['facet.field'][$key] = "{!ex=$tag}" . $facetfield;
    // Tag the respective query field with the tag.
    _ri_portfolio_alter_solr_add_field_tag($call_args, $facetfield, $tag);
    
    // What the heck is done here? See example and explanation at:
    // Example from http://drupal.org/node/1446824#comment-5632892
    // q=mainquery&fq=status:public&fq=doctype:pdf&facet=on&facet.field=doctype
    // q=mainquery&fq=status:public&fq=         doctype:pdf&facet=on&facet.field=        doctype
    // q=mainquery&fq=status:public&fq={!tag=dt}doctype:pdf&facet=on&facet.field={!ex=dt}doctype
  }  
}


/**
 * Helper function to add a tag to a solr query field for search_api_solr query.
 */
function _ri_portfolio_alter_solr_add_field_tag(array &$call_args, $change_fieldname, $tag) {
  foreach($call_args['params']['fq'] as $key => $field) {
    $fieldname_end_pos = strpos($field, ':');
    $fieldname = substr($field, 0, $fieldname_end_pos);
    if ($fieldname == $change_fieldname) {
      $call_args['params']['fq'][$key] = "{!tag=$tag}" . $field;
    }
  }
}



danielnolde’s picture

Thanks Chris for the - as always - crucial hints!! And thanks heacu for the initial suggestion/idea at http://drupal.org/node/1431926#comment-5582734 !

So, how are we going to make this happen in a generic way in apachesolr.module / search_api_solr,module?

cpliakas’s picture

Excellent!!! Let's share these findings with the appropriate maintainers so they can integrate this functionality. Then we can see what changes to Facet API might be necessary to integrate this functionality if any. In short, this has to be a coordinated effort between Search API / Apache Solr Search Integration / Facet API.

I posted a corresponding issue against Apache Solr Search Integration at comment #5, and I would suggest someone do the same to the Search API Solr search module.

Great work!
Chris

danielnolde’s picture

cpliakas’s picture

Status: Active » Fixed

Marking as fixed, because pwolanin believes this is simply "OR" facets, which is already supported by Facet API and all implementing modules. See #1448394: Support the multi-select facet feature where the associated counts are maintained as if no contraints have been applied.

Status: Fixed » Closed (fixed)

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

slapierre’s picture

Hello,

I know this issue is closed. I am running D6.26 and want to do exactly what is described here.

I can craft the query to solr to return exactly what I want (http://localhost:8983/solr/select?q=desk&fq={!tag=dt}ss_MT:Other&facet=on&facet.field={!ex=dt}ss_MT)

But I have not yet been able to make it work through Drupal. I have tweaked the params values around for hours in hook _apachesolr_modify_query(&$query, &$params, $caller) but the result set is just not filtered.

Anyone has code to share that would help me for D6?

thx

Sebastien

slapierre’s picture

Version: 7.x-1.x-dev » 6.x-3.x-dev

Hello,

I know this issue is closed. I

I can craft the query to solr to return exactly what I want (http://localhost:8983/solr/select?q=desk&fq={!tag=dt}ss_MT:Other&facet=on&facet.field={!ex=dt}ss_MT)

But I have not yet been able to make it work through Drupal. I have tweaked the params values around for hours in hook _apachesolr_modify_query(&$query, &$params, $caller) but the result set is just not filtered.

Anyone has code to share that would help me for D6?

thx

Sebastien