I'm not entirely sure if this problem stems from Search API or Views or Search API's Views integration, the problem manifests itself in my Solr query so I will raise it here and see what happens.

I have a view on a search_api_solr index with the following filters:

group 1 (exposed):
Fulltext Search
AND
group 2 (not exposed):
type='object' OR
type='publication'

which should result in q="searchterms"&fq=type:"object" OR "publication"

however it results in q="searchterms"&fq=type:"object"&fq=type:"publication"

To get around this I am hacking it in query_alter but I would like to be able to arrange the filters in Views without having to intercept them.

Am I missing some trick here or should my view work as it is?

Thanks in advance. :)

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

drunken monkey’s picture

Project: Search API Solr » Search API
Version: 7.x-1.0-beta3 » 7.x-1.0-beta8
Component: Code » Views integration

Hm, for me, this works as expected.
I'd also think the problem most likely lies in the Search API module and its Views integration, not in the Solr-specific module. (As a test, if you don't have too many nodes, you can create a database server, move the index to it, re-index and see if that solves the problem.)

group 2 (not exposed):
type='object' OR
type='publication'

You mean you have a filter on the type, and selected those two options?

Which version of the Search API are you using?

zenlan’s picture

Thanks for responding.

Search API 7.x-1.0-beta10

I set up a test on the drupal index (my example above was using a custom entity index) and attached a screenshot from the views filter group configuration.

Search API Solr ends up with the following Solr query which cannot produce any results as there are no content types that are both page AND article:

http://localhost:8080/solr/drupal/select?qf=t_title&qf=t_body:value&fq=s..."article"&fq=ss_type:"page"&fq=index_id:my_solr_index_drupal&sort=score desc&version=1.2&wt=json&json.nl=map&q="searchterms"&start=0&rows=10

If I tweak the query in the browser, using 'OR' to conjoin the fq terms, (page OR article) I get results:

http://localhost::8080/solr/drupal/select?qf=t_title&qf=t_body:value&fq=(ss_type:"article" OR ss_type:"page")&sort=score%20desc&version=1.2&wt=json&json.nl=map&q="searchterms"&start=0&rows=10

Hope that helps.

drunken monkey’s picture

Ah, judging from your screenshot the solution is quite simple: Search API doesn't support Views filter groups. Just use a normal filter on type and select both types as the filter values. That should work like expected.

zenlan’s picture

I have no requirement to do this for the Drupal index, that was just an example. I have this requirement for a read-only non-Drupal index and there is no filter of that sort for it. I would have to get the option-values from Solr in order to build the filter widget, which I was hoping to avoid.

Are there any other Views features that are not supported by Search API, are they documented somewhere?

drunken monkey’s picture

Category: bug » support
Status: Active » Fixed

Are there any other Views features that are not supported by Search API, are they documented somewhere?

Honestly, I don't know. I didn't even know about filter groups until now (or, had only heard them mentioned once or twice, in passing). As I see it, there are numerous extensions for Views (both built-in and in extension modules) that are still pretty hardcoded for the default backend, or other Views defaults, which the Search API (and other systems) replaces. These extensions then won't work with Search API views, without us having really the chance to know about them, or tell the user they aren't working. (The "Global: Random" sort would be another example that popped up just one or two days ago.)
Also, when I wrote the Views integration, there was close to zero documentation for Views 3, and some inline documentation was also simply wrong. Don't know if that has improved since then, but it's also a reason why some more fancy features might not be supported by the Search API Views integration.

zenlan’s picture

Fair enough, I feel your pain about the Views 3 documentation for sure. :)

I can live with my query_alter hack for now and if I get some spare time I'll try to take a deeper look, see if there is a proper solution.

Thanks and have a nice weekend. :)

Status: Fixed » Closed (fixed)

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

Anonymous’s picture

Version: 7.x-1.0-beta8 » 7.x-1.x-dev

@zenlan, I have a similar issue, can you share your query_alter hack please?

Anonymous’s picture

Status: Closed (fixed) » Active

I can see how to alter the global conjunction in a hook_search_api_query_alter(), like:

$query->getFilter()->setConjunction('OR');

But how to create separate groups?

This is what I'm trying to achieve:
(brand=puma AND sku=123) OR (EAN=456)

Anonymous’s picture

Just my thoughts on this: both MySQL and Solr would support "nested conjunctions", so I think this is a valuable addition to Search API.

In the case of Apache Solr, it simply comes down to rewriting createFilterQueries.
Views 3 stores the conjunction grouping like:

[filter_groups] => Array
(
  [operator] => OR
  [groups] => Array
    (
      [0] => AND
      [1] => AND
    )
)

We could allow setConjunction to have such an array.
This could be passed on the createFilterQueries ($filter).

Let me see if I can come up with a patch for this. Something like this
- search_api_views passes on the filter_groups operators
- search_api allows setConjunction to be an array()
- in createFieldsQuery functions, if conjunction is and array, then it walks through the groups and returns the correct query

zenlan’s picture

Hello,

unfortunately my hack is very specific to one particular query where the 'OR' group has known fields so it won't be very useful to anyone else. A proper patch would be desirable but alas deadlines are looming and I have little spare time at the moment, although I could probably test and tweak if that would help.

drunken monkey’s picture

Category: support » bug

The Search API already supports nested filters with different conjunctions (if you weren't aware of that). The problem is just that Views 3 documentation is sparse, to say the least, and I had no idea that there even were filter groups when I implemented the Views integration, let alone how they work (which I still don't know).

If you know what the filter handler has to check in the query() function, I could probably easily add this (once I have the time), or guide you on how to add this.
Basically, to add a new filter group that hasn't got an AND conjunction, you call $query->createFilter('OR'), fill it with the conditions and then pass it to $query->filter() – almost exactly what you'd do for a database query.
Changing a filter's conjunction (especially the one on the base level) is highly discouraged, on the other hand.

Anonymous’s picture

Thanks for the tips. I'm working on this today, will post back later.

Anonymous’s picture

Status: Active » Needs review
FileSize
5.16 KB

Hi,

attached is a patch which works for me. The patch focuses on handler_filter.inc and adds new logic to the query() function. That still needs adaptation for all other handler_filter_*.inc.

The new code creates nested conjunction filters. It is based on Views' "filter_groups" and passes on the $group level to the condition() functions, which now have a 4th argument $group = NULL.

In Search API's query.inc I added a check for $group to add filters into the new filter groups. This only influences Views' queries, or falls back to default.

Changing a filter's conjunction (especially the one on the base level) is highly discouraged, on the other hand.

Indeed. Therefore I added an extra nesting wrapper. Like so:

Search API base conjunction (usually "AND")
  -> Views nesting wrapper (AND / OR)
       -> Filter group 1 (AND / OR) 
            -> Filter 1
            -> Filter 2
       -> Filter group 2 (AND / OR)
            -> Filter 3

So there is 3 filter levels, Views. In my case, the resulting Solr $fq becomes perfectly:

Array (
    [0] => ((((ss_brands\:name:"Puma") (ss_mpn:"069322"))) OR (ss_gtin:"NOT-AVAILABLE"))
)

@todo: make the handler_filter.inc code more general for all handler_filter_*.inc files.
@todo: prepare for even more nested levels? (Views only has 1 level of filter groups)

drunken monkey’s picture

Great job, thanks a lot! I'm sorry I can't test/review right now, as I'm completely buried in work, but I'll get back to this issue ASAP.

Anonymous’s picture

Status: Needs review » Needs work

No problem at all, take it easy ;)

I just realized that my patch only works for 2 filter groups, for example:
((A OR B) AND* (C OR D))

I didn't think about 3 or more groups:
((((A OR B) OR* (C AND D)) AND* E) OR* (F AND G))

...and then imagine nested groups as well:
((((A OR B) OR* ((C AND D) OR** (H OR I))) AND* E) OR* (F AND G))

* = Views filter groups conjunction
** = nested groups (not supported by Views, but has potential for Search API to do complex queries)

This is getting really complex as you see... If I have free time, I will work more on this. I'd like to help make Search API the most powerful search tool for Drupal.

drunken monkey’s picture

Status: Needs work » Needs review
FileSize
7.99 KB

OK, I finally managed to look at this.
First off, thanks again for helping with this! Your code made it pretty clear what was to do, and it also already seemed to work quite well. However, I think having this functionality bundled centrally in the Views query class is the best way to do this. We can care about creating the needed nested filters there, when they are needed, and keep changes to the filter handlers at a bare minimum.

Please see, test and review the attached patch. Sorry that there are some cosmetic changes (array_shift() => reset(); comment changes) in there, too. The main thing is I added the filter group to all calls to condition() and filter(), there just collected the information and then later added them to the query during build(), which is the way it's „supposed“ to work anyways, I guess.

@todo: prepare for even more nested levels? (Views only has 1 level of filter groups)

I don't think that's likely to ever come (and certainly only between major versions). It would be a UI nightmare and, unless I'm totally mistaken, all possible logic operations can be expressed (albeit with some redundancy) with ANDed ORs (or ORed ANDs) anyways.

drunken monkey’s picture

That one is better, as it correctly adds conditions/filters without a group directly to the query (important, e.g., for argument handlers).

Anonymous’s picture

Status: Needs review » Reviewed & tested by the community

Yes it works for me (#18), your approach is much "cleaner".
Many thanks for this.

drunken monkey’s picture

Status: Reviewed & tested by the community » Fixed

Great, committed.

Status: Fixed » Closed (fixed)

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

Sebastian.Buesing’s picture

Status: Closed (fixed) » Needs work

Now, while this patch may fix what it does it seems that the way SearchApiViewsQuery handles filtering could use some extra work.

This worked well before:

function my_module_views_post_build(&$view) {

$search_api_query_filter = new SearchApiQueryFilter();
// build a nice filter
$view->query->filter($search_api_query_filter);
}

now I have to change it to:

function my_module_views_post_build(&$view) {

$search_api_query_filter = new SearchApiQueryFilter();
// build a nice filter
$view->query->filter($search_api_query_filter, 1);
$view->query->build($view);
}

if I want the extra filter to be passed down to the SearchAPI Query. I don't think I should have to call build() here again, should I or shouldn't I add a filter at that point?

zambrey’s picture

Can grouping be used with fulltext search?

For example I have two exposed filters - one is fulltext search and the other is sku (from commerce). I defined OR group but cannot make it to work when both filters are applied.

It works ok when searching on other fields like title and body.

legolasbo’s picture

Issue summary: View changes
Status: Needs work » Closed (outdated)

This issue has not seen activity in over 2,5 years. I am therefore closing this issue to clean up the issue queue. Feel free to re-open and update this issue if you feel this issue is still relevant and of importance.