First, see http://drupal.org/node/1823590. This patch was to support adding a tag to various select queries in order to allow modules to exclude content from being indexed older than N days.

I think i'm finding though that in the case of a mass reindex (via the "Queue all content for reindexing" button) the "changed" date in apachesolr_index_entities_node table becomes REQUEST_TIME in apachesolr_index_node_solr_reindex (~ line 867):

  $select = db_select('node', 'n');
    $select->condition('status', 1);
    $select->addExpression("'node'", 'entity_type');
    $select->addField('n', 'nid', 'entity_id');
    $select->addField('n', 'type', 'bundle');
    $select->addField('n', 'status', 'status');
    $select->addExpression(REQUEST_TIME, 'changed');

The effect is all content is reindexed - not just content newer than 10 years (in the related ticket linked above). Am I wrong? I would be happy to contribute if this is indeed an issue but we have the same requirement as in http://drupal.org/node/1823590.

Thanks for the help!

Comments

blazindrop’s picture

Assigned: Unassigned » blazindrop
Category: support » feature
Status: Active » Needs review
StatusFileSize
new685 bytes

I have done quite a bit of research on my particular issue. I've also reviewed http://drupal.org/node/1828014 to see if my idea was superceded by work done there, which it is not. So...

The Problem

I come from a business where there's a lot of aggregated news content placed on our sites. This content is indexed in our SOLR index and in particular (this "news" content) accounts for a large percentage of our content online across 20+ sites. The thing is with news content it goes old -- quick. We have decided to exclude all news content older than 1.5 years from our search index. All other content should remain.

The way Apache SOLR reindexes content doesn't allow customization of the query that selects nodes from the node table. Within apachesolr_index_node_solr_reindex, we have:

 ...
   $insert = db_insert($indexer_table)
      ->fields(array('entity_id', 'bundle', 'status', 'entity_type', 'changed'))
      ->from($select)
      ->execute();
 ...

Furthermore, you cannot use addTag() here because DBTNG does not allow that for insert queries, nor will addTag() fire when this particular query uses from($select) as the text for that query is used as-is.

The Solution

Within apachesolr_index_node_solr_reindex, add this line of code before the above query is executed to allow other modules to modify the query:

  drupal_alter('apachesolr_index_node_reindex_query', $select);

I have attached a patch that I've tested locally (along with our custom rules to exclude content over a certain age).

blazindrop’s picture

Title: Mass reindexing content newer than X days » Allow modules to modify query used to select nodes for reindexing
pwolanin’s picture

Status: Needs review » Needs work

I think this is a "won't fix" for this particular patch.

This would seems to be a good use case for hook_apachesolr_ENTITY_TYPE_exclude()?

i.e. function MYMODULE_apachesolr_node_exclude($entity_id, $row, $env_id)

You'd still be fetching the rows, but could avoid indexing them.

As an alternative, you could us the tag to modfy the query in apachesolr_index_get_entities_to_index and add a JOIN and WHERE to the node table? Did you try that?

We could also consider changing apachesolr_index_node_solr_reindex() to get the actual changed time - I think perhaps the problem is that non-node entities don't have a changed field, so Nick might have done this to make the logic generic?

nick_vh’s picture

function hook_apachesolr_entity_info_alter(array &$entity_info) {
  $entity_info['node']['reindex callback'] = 'my_custom_module_apachesolr_index_node_solr_reindex';
}

This should solve it without hacking the module

blazindrop’s picture

Status: Needs work » Needs review

Peter, good suggestions - thanks. I will look over those two alternatives and report back. I was hesitant to propose a change to "changed" since there seemed like a lot of work surrounding that in another issue, but I'm sure one of these two alternatives will work fine :)

blazindrop’s picture

Re: #4, I feel this is overkill for my situation. I don't care to reimplement the whole reindexing logic -- I just need to control whether a node should be indexed base on some of it's native criteria. This is a very nice addition, though, to the API which may prove very helpful later :) Thanks for the suggestion.

blazindrop’s picture

StatusFileSize
new661 bytes
new25.25 KB
new26.99 KB

Peter I did some research on your suggestions. hook_apachesolr_ENTITY_TYPE_exclude() would fit the bill but like you said it would scan all rows and still not give me the node's created date.

Doing the join worked nicely in apachesolr_index_get_entities_to_index. However, there's a side effect on the apache solr status page. Because I am excluding items within this hook callback, the status query assumes there's no filtering and it saying for my case 9% was already sent to the server. For example:

before_add_tag.png - status page after I cleared my local index (verified no docs via solr status page) with my custom hook callback
after_add_tag.png - status page after I cleared my local index WITH the attached patch applied with my custom hook callback

Is this patch a good idea?

Status: Needs review » Needs work

The last submitted patch, 1925026-count-query-tag.patch, failed testing.

blazindrop’s picture

Status: Needs work » Needs review

#7: 1925026-count-query-tag.patch queued for re-testing.

blazindrop’s picture

StatusFileSize
new1.38 KB

I am finding that the patch (or the concept) I originally created in #1 limits the population of the apachesolr_index_entities_node table based on custom criteria (node age for example). While I did find a workaround to reduce my selection set for indexing using the join pwolanin suggested, I'm running into another issue when implementing my own custom cron hook to remove old items on a rolling basis because there is no way to find out exactly what nodes are in SOLR without querying solr directly.

Attached is a revised patch to solve an error when running cron when implementing hook_apachesolr_index_node_query_alter. For any queries using addTag() they all should use consistent table aliases (which is what caused the error).

nick_vh’s picture

+++ b/apachesolr.index.incundefined
@@ -1329,12 +1333,12 @@ function apachesolr_index_node_check_table() {
-  $query = db_select($table, 'aien')
+  $query = db_select($table, 'aie')
     ->fields('n', array('nid', 'status'))
-    ->where('aien.status <> n.status')
+    ->where('aie.status <> n.status')
     ->range(0, ($limit * 2))
     ->addTag('apachesolr_index_node');
-  $query->innerJoin('node', 'n', 'n.nid = aien.entity_id');
+  $query->innerJoin('node', 'n', 'n.nid = aie.entity_id');
   $nodes = $query->execute()->fetchAllAssoc('nid');

why the change? This does not change anything. Perhaps you have to change the first query to use aien? I guess I'm not entirely following your reasoning why it has to be the same?

nick_vh’s picture

Status: Needs review » Postponed (maintainer needs more info)
blazindrop’s picture

Re: #11, the reason for the table alias changes (aien to aie) is to make the alias in this function more consistent with other parts of the contrib code that are calling addTag() on the same value; any queries tagged with the same string all should use the same aliases.

With this patch, the following custom code becomes possible (which we're using with good results in production):

// custom code to exclude content of a certain type over a certain age from the solr index
function hook_query_apachesolr_index_node_alter(QueryAlterableInterface &$query)
{
	$timestamp_min = strtotime('-18 months', REQUEST_TIME);
	$query->join('node', 'n_custom', 'n_custom.nid = aie.entity_id');
	$query->condition(db_or()
		->condition('n_custom.type', 'news', '!=')
		->condition('n_custom.created', $timestamp_min, '>'));
}

Without this patch, you'd need some extra conditionals to find the table alias for apachesolr_index_entities_node. Does that help?

blazindrop’s picture

Status: Postponed (maintainer needs more info) » Needs review

Flipping to needs review since maintainer was given info :)

nick_vh’s picture

Version: 7.x-1.x-dev » 6.x-3.x-dev
Status: Needs review » Patch (to be ported)

Testbot is doing crazy as I *know* it can apply. Committed to 7.x-1.x and in need of a backport Wrong issue

nick_vh’s picture

Version: 6.x-3.x-dev » 7.x-1.x-dev
Status: Patch (to be ported) » Needs review
nick_vh’s picture

Version: 7.x-1.x-dev » 6.x-3.x-dev
Status: Needs review » Patch (to be ported)

Committed, needs backport to 6.x-3.x

nick_vh’s picture

Issue summary: View changes

removing line of code I added for testing addTag

joseph.olstad’s picture

Version: 6.x-3.x-dev » 7.x-1.x-dev
Issue summary: View changes
Status: Patch (to be ported) » Fixed

leave this as fixed

Status: Fixed » Closed (fixed)

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