3

I have implemented a custom entity type which is essentially identical to what the Model module does, with a few additional fields.

I have followed the Apachesolr User module to understand how to index my custom entities in the solr index. But when I add, or update and existing, entity the solr index is not automatically picking up the changes.

/**
 * Implements hook_apacheolr_entity_info_alter().
 */
function my_entity_apachesolr_entity_info_alter(&$entity_info) {
  $entity_info['my_entity']['indexable'] = TRUE;
  $entity_info['my_entity']['status callback'][] = 'my_entity_status_callback';
  $entity_info['my_entity']['document callback'][] = 'my_entity_solr_document';
  $entity_info['my_entity']['reindex callback'] = 'my_entity_solr_reindex';
  $entity_info['my_entity']['index_table'] = 'apachesolr_index_entities_my_entity';

  $entity_info['my_entity']['result callback'] = 'my_entity_result';
}

This is the hook I had to implement to index my content, the various callbacks are irrelevant. It is worth noting the index table needs to be implemented in hook_schema() as well. This can be easily seen in Apachesolr User

3 Answers 3

4

Originally I thought I had to implement my own hooks but after seeing that apachesolr took care of deletes I wondered why it hadn't taken care of my updates and inserts.

There is actually a apachesolr_entity_update/insert() which calls apachesolr_entity_should_index(). That checks whether your entity info (returned by entity_get_info($entity_type)) has the following key set:

$info['bundles'][$bundle]['apachesolr']['index']

Where $bundle is the $entity bundle. This made it pretty easy for me to figure out that I just had to add some stuff to my hook_entity_info_alter():

function my_entity_entity_info_alter(&$entity_info) {
  foreach (my_entity_get_types() as $type => $info) {
    $entity_info['my_entity']['bundles'][$type] = array(
      'apachesolr' => array('index' => TRUE),
    );
  }
}

After adding that and clearing cache I no longer needed my entity update/insert hooks.

Note: Don't get this confused with hook_apachesolr_entity_info_alter like I did!

Original Answer

I found the function apachesolr_index_get_entities_to_index() which checks the indexer table for your entity_type for a changed timestamp that's greater than what it's last seen (I have yet to find out where it sets that). Essentially we just need to automate the updating of that table. This can be done with 2 hooks:

hook_entity_insert() hook_entity_update()

/**
 * Implements hook_entity_insert().
 */
function my_entity_entity_insert($entity, $type) {
  // Update our indexer table
  if ($type != 'my_entity') {
    return;
  }
  $indexer_table = apachesolr_get_indexer_table($type);

 // Insert the new entity into a fictional table of all entities.
  $info = entity_get_info($type);
  list($id) = entity_extract_ids($type, $entity);
  db_insert($indexer_table)->fields(array(
    'entity_type' => $type,
    'bundle' => $entity->type,
    'entity_id' => $id,
    'changed' => REQUEST_TIME,
  ))->execute();
}

/**
 * Implements hook_entity_update().
 */
function my_entity_entity_update($entity, $type) {
  // Update our indexer table
  if ($type != 'my_entity') {
    return;
  }
  $indexer_table = apachesolr_get_indexer_table($type);

  db_update($indexer_table)
    ->fields(array(
      'changed' => REQUEST_TIME,
    ))
  ->condition('entity_id', $entity->entity_id)
  ->execute();
}

You may have to add this line into the insert statement in hook_entity_insert() if you have a status coming from $entity (mine is always 1 so the db table defaults it to that).

'status' => $entity->status,

Edit: You may be wondering "What about delete??", this seems to be taken care of by apachesolr_entity_delete, I'm going to see why apachesolr_entity_update and apachesolr_entity_insert didn't take care of my entities. However this answer is still valid.

0

I develop a custom module to create a new entity "my_entity" on drupal 7. I use:

  • my_entity_entity_info() ==> Declare my new entity.
  • my_entity_schema() ==> create the database table.

Then, I'd like to make this entity available for apache solr indexing.

Do I have to create only the hook "my_entity_entity_info_alter" into my custom module as you described above? Do I need to implement the hook "my_entity_apachesolr_entity_info_alter" too?

I'm very confused with these two hooks "my_entity_entity_info_alter" and "my_entity_apachesolr_entity_info_alter".

 function my_entity_entity_info_alter(&$entity_info) {
     foreach (my_entity_get_types() as $type => $info) {
          $entity_info['my_entity']['bundles'][$type] = array(
          'apachesolr' => array('index' => TRUE),
          );
     }
 }

Thanks a lot

1
  • Hi @cyrilT you do need to implement both hooks. The Apache Solr User module is a great module to look through to help you understand how to implement your own custom entities as this does the same thing for the user entity. In general hook_apachesolr_entity_info_alter will tell apachesolr to index your entities through the callbacks defined. The hook_entity_info_alter makes sure that the apachesolr module knows to index the content on insert and update. Hope that helps! Commented Jan 7, 2014 at 19:40
0

Thank you so much for your help. It was very confusing at the beginning but I figured out how Apache solr handles an entity.

This is the process I implemented:

1 - my_entity_entity_info() ==> Declare my new entity into a custom module.

2 - my_entity_schema() ==> create the entity database table for this new entity

3 - my_entity_entity_info_alter() ==> to mark this entity indexable by Apache solr

function my_entity_entity_info_alter(&$entity_info) {
     $entity_info['my_entity']['apachesolr']['indexable'] = TRUE;
}

4 - my_entity_apachesolr_entity_info_alter() ==> to tell Apache solr to index your entities "my_entity" through the callbacks defined.

function my_entity_apachesolr_entity_info_alter(&$entity_info) {
  $entity_info['my_entity']['indexable'] = TRUE;
  $entity_info['my_entity']['status callback'] = 'my_entity_status_callback';
  $entity_info['my_entity']['document callback'][] = 'my_entity_document';
  $entity_info['my_entity']['reindex callback'] = 'my_entity_solr_reindex';
  $entity_info['my_entity']['index_table'] = 'my_entity_index_entities_my_entity';
}

For information:

  • ['status callback'] = 'my_entity_status_callback'; ==> Is this entity ready to be indexed?
  • ['document callback'][] = 'my_entity_document'; ==> Which data to send to Apache Solr?
  • ['reindex callback'] = 'my_entity_solr_reindex'; ==> to refresh the entity index database table where Apache solr takes a look to know what to send
  • ['index_table'] = 'my_entity_index_entities_my_entity'; ==> the entity index database table name -- that is different than the table defined in the hook my_entity_schema() -- DON'T GET CONFUSED!! Apache solr has is own database table for entity information.

Correct me if I wrong. Thanks

I hope that could help some other folks as myself after hours surfing on forums and banging my head against the wall.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.