Hi,

i am having a problem when i try to place several blocks each one with a solr views different query in my page. The problem is that apachesolr module has a static cache that prevents to run more than one query per page, this seems to be a problem to apache solr views module, cause it is a common use case to have several blocks running querys in the same page.

Diagnosys:
In apachesolr.module in the method:

function apachesolr_do_query(DrupalSolrQueryInterface $current_query) {
...
if ($response = apachesolr_static_response_cache($searcher)) {
    // Return cached query object
    return array($query, $response);
  }

is where the static cache is placed, it depends on searcher_name, constructed in Solr_Base_Query in apachesolrviews:

/**
   * Get query searcher name (for facetapi, views, pages, etc).
   */
  public function getSearcher() {
    return $this->name . '@' . $this->solr->getId();
  }

And it depends of: (located in apachesolr_views_query.inc

$query = new ApachesolrViewsSolrBaseQuery('apachesolr', $solr, $params, '', current_path());

I propose to change the name of the searcher depending of the view name and display id being used as follows:

$query = new ApachesolrViewsSolrBaseQuery('apachesolr' . $view->name . $view->current_display, $solr, $params, '', current_path());

My first code uses only a display and i modify the query in a hook but with that use case i cannot figure how can i prevend this static cache. ¿any ideas?

If you think my solution is correct i can send a patch.

Best
David

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

david.gil’s picture

Priority: Normal » Major

Uhmmmm testing more this idea it brokes facets if they are in the same page that the view, cause facets use this ID to avoid other searchs.

I have been trying to avoid static cache of the query, but there is no hooks where we can change this, so we have a problem to use apache solr views with more than one view per page. ¿any idea?

cr0ss’s picture

I've run into the the same issue:

$data = array(
  'documents' => views_embed_view('brief_related_content', 'documents', $content),
  'videos' => views_embed_view('brief_related_content', 'videos', $content),
  'course_modules' => views_embed_view('brief_related_content', 'course_modules', $content),
);

This simple code returns 1st rendered view 2 more times.

david.gil’s picture

Hi Cr0ss, if you are in a hurry and you dont have facets in the same page, you can use as a temporal solution what i comment in the issue. But we need a better solution, now i cannot figure how to solve this in a clean way.

Best

Fabianx’s picture

I used a workaround for now:

Its not ideal, but works:

$data = views_embed_view('view_name', 'default');
drupal_static_reset('apachesolr_static_response_cache');

Could also do it in an after_execute view hook.

The last executed view is then used for the facets like normal ...

david.gil’s picture

For me #4 is enough, at least when you embed the view in code, for a more robust solution it could be necesary to add a config to the view, cause in other modules (context, panels...) it is not posible to use that without coding.

Best

TechNikh’s picture

#4 works. Thanks Fabianx

function modulename_views_post_execute(&$view) {
  if($view->name == "my_view_name"){
    drupal_static_reset('apachesolr_static_response_cache');
  }
}
yaelsho’s picture

Hello,
I've view page with views attachment.
Without the attachment the facet are working with/without chache enabled.
With the attachment, it is not working, probably due to the fact of 2 views in the same page.
I was trying to implement the code in #6 in custom module, but it appears to remove the facet both on page with/without attachment.
Do you have any idea why it should be different in case of 2 views blocks (like described above) comparing to view page with attachment?
Thanks, Yael

catch’s picture

Status: Active » Needs review
FileSize
898 bytes

This is because the $name parameter passed to the constructor when instantiating the query object is used as the key for the static cache in apachesolr.module, and apachesolr_views always passes it as 'apachesolr'.

Arguably apachesolr module should take the query parameters into account when building the static cache, not just the 'searcher' name. I'll open an issue over there and cross-link.

However for now here's a patch that solves this for me within apachesolr_views.

MiroslavBanov’s picture

The patch #8 does fix some problems for me, but I still have a problem when I have exposed filters in panel pane configuration, with exposed pagination settings. My setup is simple - 1 view with 1 content pane display, with exposed "Items per page", and different number of items set in each pane. I am not sure if this is even the correct approach, but with modification to patch #8, I was able to make it work. Patch attached.

MiroslavBanov’s picture

Reroll of patch #9 applied after patch: https://drupal.org/comment/8219315#comment-8219315
Ignore this if you haven't applied https://drupal.org/comment/8219315#comment-8219315

MiroslavBanov’s picture

Status: Needs review » Needs work

I think #8, #9, #10 are not really using the correct aproach. This patch appears to fix the problem: https://drupal.org/node/2276991#comment-8833069

no.exploit’s picture

#4 works. Thanks Fabianx

a_godin’s picture

Hi, is there also a problem when having multiple queries for a view ?

With, with Apache Solr Views, I created a view with some exposed filters (a textbox, and a bunch of checkboxes on 2 taxonomy vocabularies) to satisfy very picky specs.

When a user launches a text search (with or without checking the box of some taxonomy terms), the taxonomy term's labels that match the results must be highlighted so the user knows which taxonomy terms he can use to narrow his search. Also, the WHERE conditions must be OR, not AND. I was able to do that by creating the same query that is used in my view using template_preprocess_views_view__viewname, checking the facet count of the response and modifying the $variables['exposed'] value to put in bold the labels of the taxonomy terms that had results. I couldn't use the response of the query passed in the function parameters because its facet count only takes into account the first 10 results ... I needed all of them. I also modified the query in mymodule_apachesolr_query_prepare to change the query's WHERE condition from AND to OR.

So that works well enough.

Now I'm asked to, if a user launches a text search and he also checked the box of some taxonomy terms, to highlight the taxonomy term's labels as if the user had not also checked some taxonomy terms ... to let the user know in which taxonomy terms the text he's searching for was found, regardless of what taxonomy term checkboxes he selected.

So I created another query in template_preprocess_views_view__viewname and modified that query in mymodule_apachesolr_query_prepare so that it removes the filters on the taxonomy terms ... but the results of that query are always the same as the results of the first query I created in template_preprocess_views_view__viewname.

I applied the patches suggested here but my queries still return the same result and I don't know what to do ... any hints or suggestions are appreciated.

Thanks !

MiroslavBanov’s picture

Apachesolr caches the queries based on 'name'. You could try changing the name in the ApachesolrViewsSolrBaseQuery constructor in apachesolr_views_query.inc to something unique.

$query = new ApachesolrViewsSolrBaseQuery(uniqid($view->name), $solr, $this->query_params, '', current_path());

For an actual solution to this issue, I prefer to do something like https://www.drupal.org/node/2276991#comment-9087873, and not to use apachesolr_do_query() at all, because it doesn't work well with apachesolr_views. Unfortunately, this would remove all facetapi integration, and also you wouldn't be able to use hook_apachesolr_query_prepare(). So I will probably need to implement an alternative method that does at least part of what apachesolr_do_query() does.

a_godin’s picture

Thank you for the quick response.

Changing the name in the ApachesolrViewsSolrBaseQuery constructor gives me an error : Exception : HTTP 400; null: null dans DrupalApacheSolrService->checkResponse() (ligne 455 dans C:\Program Files (x86)\Zend\Apache2\htdocs\atrium\sites\all\modules\apachesolr\Drupal_Apache_Solr_Service.php).

So if I use $response = $query->search() instead of apachesolr_do_query(), I can create more than one query in code with no problem ?

And if I modify my query filters before I do $query->search(), that's the same thing that calling hook_apachesolr_query_prepare() does, right ?

MiroslavBanov’s picture

Well, there are a lot of things that apachesolr_do_query() does, so I can't say that is exactly the same.

In your case, you should be able to use $query->search(), hack a alter hook somewhere between the $query = new ApachesolrViewsSolrBaseQuery and the $query->search(), and solve your problem.
Alternatively, you can use $query->search(), make $query_params property public, and use hook_views_query_alter() to change the $query->query_params, before it has been used by the constructor.

Edit: I am not getting any exceptions when I change the solr query name.

hefox’s picture

Status: Needs work » Needs review
FileSize
694 bytes

Patch overrides searcher for view querys to include name, args, display of current view.

I don't think skipping over do_query is a good idea.

hefox’s picture

Attempt 2

In order to use facets, need to use the apachesolr@env cause that's pretty damn hard coded atm.

However, under the logic that views that are multi on a page won;t being using facets added an option to use a customer searcher name, else fallback to current.

MiroslavBanov’s picture

I like the direction of the last attempt. It is close to what I had in mind. To have a check that prevents faceting, but allows multiple views on one page.

But I was thinking of dispensing with apachesolr_do_query() and doing something different. Because there is no way to have pager offset, while using it.

hefox’s picture

IMO patching apachesolr_do_query to allow pager offset would be best, so if it changes won't have to update apachesolr_views.

But that's for the other ticket to figure out

MiroslavBanov’s picture

@hefox
Maybe you're right. Patching apachesolr_do_query() could be the answer. Only as last resort, a different version of apachesolr_do_query() should be implemented. But this is part of the other issue.

I hope to get some reviews by the community on the patch #18, and hopefully we can resolve this.

marcvangend’s picture

If it helps someone... As a workaround, I have added an incrementing static variable to the class (

static protected $searcher_increment = 0;

). If it's 0, I'm not changing the searcher name, so the facets remain working for the first view on any given page. Additional views get a different name based on the increment.

      // The default searcher name is 'apachesolr'. It must be for facetapi to
      // function properly.
      $searcher_name = 'apachesolr';
      // If $searcher_increment is greater than 0, there must be multiple solr
      // views on this page. We create a different searcher name, thus losing
      // the ability to use facets with these views.
      if (self::$searcher_increment != 0) {
        $searcher_name .= '_' . self::$searcher_increment;
      }
      // Increment the variable.
      self::$searcher_increment++;
      // Build the query and proceed as usual.
      $query = new ApachesolrViewsSolrBaseQuery($searcher_name, $solr, $this->query_params, '', current_path());
Mina.Habashy’s picture

In my case, there exist facets and I need to use solr views in same page.
I tried both #4 & #17.

#4 solved the solr views issue but the facets disappeared!!

#17 Works with me and the facets appeared again.
Thanks so much hefox.

pcho’s picture

Status: Needs review » Reviewed & tested by the community

#4 was crucial to busting the repeating views problem (it was killing me as I was wondering why views_embed_view() refused to change).
#18 is also useful to clean up the side effects, as well.

Would it make sense to inject #4 in certain places so we don't have to hard code this into our integration code?

The last submitted patch, 8: apachesolr_views-1766254-8.patch, failed testing.

The last submitted patch, 9: apachesolr_views-1766254-9.patch, failed testing.

MiroslavBanov’s picture

Status: Reviewed & tested by the community » Needs review

@pcho
Doesn't #18 alone fix your particular case? If not, then it would be useful if you can debug why this happens, and to give some details that will help improve on it.

MiroslavBanov’s picture

Status: Needs review » Needs work

Patch no longer applies.

Also, I think that we should adjust the searcher to use a simple static increment. The option with the concatenations and implode of things in the $view is prone to errors, I believe.

NewZeal’s picture

I found that I could successfully display two apachesolr view searches on the same page by clearing the query cache in the pre_view stage as follows:

function est_apachesolr_views_pre_view(&$view) {
  if($view->name == "my_view_name"){
    drupal_static_reset('apachesolr_static_response_cache');
  }
}

Not only am I able to modify the query using hook_apachesolr_query_alter() but also my facets continue to work on the page.

I did find, however that I needed to cache the query arguments for my secondary View which I have embedded as a block in my main view to display results that fit the modified parameters:

function MYMODULE_apachesolr_query_alter($query) {
  // The page query is done first and this is the only one with all the relevant parameters so we cache it
  // And use it for the secondary query
  $fq = &drupal_static(__FUNCTION__);
  $context = $query->getContext();
  if ($context['view_name'] == 'my_view_name' && $context['current_display'] == 'page') {
    $fq = $query->getParam('fq');
  }
  if ($context['view_name'] == 'my_view_name' && $context['current_display'] == 'block_1') {
    $args = $fq[0];
    ....
    ....
  }
}

No module hacks required.

marcvangend’s picture

Thanks for sharing, New Zeal. Manually clearing caches sounds as if this solution could have performance drawbacks. Did you look into that?

NewZeal’s picture

Hi Marc, it is only the query cache that is being cleared. In my case I have two views working on the same page, each producing different results. The fact that I have two search queries working on the page is a performance hit but that is what is requested. Presumably because I am using solr rather than views queries I reckon search is a lot faster.

MiroslavBanov’s picture

Status: Needs work » Needs review
FileSize
3.46 KB

I tried my idea with replacing the apachesolr_do_query() with something more more suited for views. This is including the work done on #2276991: Pager offset value is always resetting 0.

herved’s picture

Thanks everyone.
I'm stuck with apachesolr right now and I confirm the patch #1766254-32: Problem with multiple views (or displays) in same page works well for me.

jonketo’s picture

jonketo’s picture

I had the same problem with a view on a search page, so I overrode the getSearcher method in the ApachesolrViewsSolrBaseQuery class.

  /**
   * Get query searcher name (for facetapi, views, pages, etc).
   */
  public function getSearcher() {
    return $this->name . '@' . $this->solr->getId() . "." . $this->view->name;
  }
jonketo’s picture

Version: 7.x-1.x-dev » 7.x-1.1-beta1
jonketo’s picture

MiroslavBanov’s picture

@joneketo

#37 attachment is not a valid patch. Read up about how to create patches in the relevant documentation page.

MiroslavBanov’s picture

Version: 7.x-1.1-beta1 » 7.x-1.x-dev

Also patches are created against dev version.