2

I am using Seach API, Solr Search modules in my website for searching. I've created an index, say 'Blogs index', I've selected blogs content type to index Fields - title, body, Author are added to index.

Created the View for the search results.

Issue is when I search the name of the author, I'm getting no relevant results. Result should be the list of blogs written by the searched author.

field Author is an entity reference field referencing the content type 'Blog Author' and is a multi-valued field. Any help is appreciated.

2 Answers 2

1

To allow nested Facet searches, based on referenced entity's titles ($target->field_title->value), in our Drupal 8 site we defined a custom-field with a processor
(which create and sets our my_titles_field field);

Place the MyCustomProcessor.php file in modules/custom/my_module/src/Plugin/search_api/processor/ directory;

With contents like below:

<?php

namespace Drupal\my_module\Plugin\search_api\processor;

use Drupal\Core\Entity\EntityInterface;
use Drupal\search_api\Datasource\DatasourceInterface;
use Drupal\search_api\IndexInterface;
use Drupal\search_api\Item\Field;
use Drupal\search_api\Item\ItemInterface;
use Drupal\search_api\Plugin\PluginFormTrait;
use Drupal\search_api\Processor\ProcessorPluginBase;
use Drupal\search_api\Processor\ProcessorProperty;

/**
 * Allows finding by titles associated (with field_references entities).
 *
 * @SearchApiProcessor(
 *   id = "my_custom_processor",
 *   label = @Translation("My Custom Processor"),
 *   description = @Translation("Allows filtering by entity-reference's titles."),
 *   stages = {
 *     "add_properties" = 0,
 *   },
 *   locked = true,
 *   hidden = true,
 * )
 */
class MyCustomProcessor extends ProcessorPluginBase {

  use PluginFormTrait;

  const ENTITY = 'node';
  const DATASOURCE = 'entity:' . self::ENTITY;
  const FIELD_NAME = 'my_titles_field';

  /**
   * {@inheritdoc}
   */
  public function getPropertyDefinitions(DatasourceInterface $datasource = NULL) {
    $properties = [];

    // Ensures our field is in General section, else we would check:
    // ```
    // if ($dataSource && $dataSource->getEntityTypeId() == self::ENTITY) {
    // ```

    if (!$datasource) {
      $property = new ProcessorProperty([
        'label' => $this->t('Entity-title'),
        'description' => $this->t('Attached Entity-ref title list'),
        'type' => 'object',
        'is_list' => FALSE,
        'hidden' => FALSE,
        'processor_id' => $this->getPluginId(),
      ]);
      $properties[self::FIELD_NAME] = $property;
    }

    return $properties;
  }

  /**
   * {@inheritdoc}
   */
  public function addFieldValues(ItemInterface $item) {
    // Loads actual entity (which $item represents).
    $entity = $item->getOriginalObject()->getValue();
    if (!($entity instanceof EntityInterface)) {
      return;
    }

    // Generate searchable JSON object (that is returned to Search-API callers
    // and which we can edit as we like to fit our needs).
    $json = [];
    $references = $entity->get('field_references');
    foreach ($references->referencedEntities() as $key => $target) {
      $json[$target->id()] = [
        'value' => $target->field_title->value,
      ];
    }

    // At last, assign our custom filter-criteria value as an index field.
    $fields = $item->getFields(FALSE);
    $fields = $this->getFieldsHelper()
      ->filterForPropertyPath($fields, NULL, self::FIELD_NAME);
    foreach ($fields as $field) {
      $field->addValue($json);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function preIndexSave() {
    // For General fields:
    $this->ensureField(null, self::FIELD_NAME);

    // For content this would look like:
//    foreach ($this->index->getDatasources() as $sourceId => $dataSource) {
//      if ($dataSource && $dataSource->getEntityTypeId() == self::ENTITY) {
//        $this->ensureField($sourceId, self::FIELD_NAME);
//      }
//    }
  }
}

Note that the field needs to added to your index by clicking Add fields in /admin/config/search/search-api/index/__my_index__/fields route manually.

For Drupal-7 See also Cross-entity searches

0

I haven't tried this with Search API but if your "Author" is a separate content type and not the actual default Author field you need to add the Relationship for that Entity reference field (for the "Blog Author" content type).

Different Content types store data in different database tables. Relationships introduce that other table data into your Views.

You'll probably have to add the Title field using that Relationship (which is, I presume, your blog author name), and include that field in the Search API settings so it gets searched.

Entity reference fields only store the ID of the referenced entity, so using them alone won't let you search the actual Title field text of the referenced entity. You can only do that through the Relationship and the relevant Title field (or however you named that field).

Your Answer

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

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