Drupal 8: Search API. Программно добавить данные в индекс.

Аватар пользователя kosskren kosskren 11 сентября в 14:29

Всем привет.

Сделал программное добавление данных в индекс. Данные представляют из себя список характеристик, закрепленных за нодой.

Поиск по этим характеристикам работает отлично, но не хватает вот чего:
search api сохраняет индексы в таблицу, где в столбце "item_id" указана нода.

Пример таблицы:

Как видим значение "entity:node/1013:ru" прекрасно позволяет получить ноду при поиске.
Мне нужно к "entity:node/1013:ru" добавить еще номер характеристики. к примеру так "entity:node/1013:ru:412".

Так вот вопрос, можно ли как о при программном добавлении индексов, влиять на значение столбца "item_id"?

з.ы.: если кратко о задаче, которую делаю. Поиском находим товар. При переходе в товар. надо отобразить нужную характеристику, по которой нашелся товар.

Индексы вот так добавляю:

namespace Drupal\oc_product_variants\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\ItemInterface;
use 
Drupal\search_api\Processor\ProcessorPluginBase;
use 
Drupal\search_api\Processor\ProcessorProperty;

/**
 *
 * @SearchApiProcessor(
 *   id = "product_variants_search",
 *   label = @Translation("Product variants search"),
 *   description = @Translation("Product variants search"),
 *   stages = {
 *     "add_properties" = 0,
 *   },
 *   locked = true,
 *   hidden = true,
 * )
 */
class ProductVariantsSearch extends ProcessorPluginBase {

  

/**
   * {@inheritdoc}
   */
  
public static function supportsIndex(IndexInterface $index) {
    foreach (
$index->getDatasources() as $datasource) {
      if (
$datasource->getEntityTypeId() == 'node') {
        return 
TRUE;
      }
    }
    return 
FALSE;
  }
  
  
/**
   * {@inheritdoc}
   */
  
public function getPropertyDefinitions(DatasourceInterface $datasource NULL) {
    
$properties = [];

    if (!

$datasource) {
      
$definition = [
        
'label' => $this->t('Product variants'),
        
'description' => $this->t('Product variants search'),
        
'type' => 'string',
        
'processor_id' => $this->getPluginId(),
      ];
      
$properties['product_variants_search'] = new ProcessorProperty($definition);
    }

    return 

$properties;
  }

  

/**
   * {@inheritdoc}
   */
  
public function addFieldValues(ItemInterface $item) {
    
$entity $item->getOriginalObject()->getValue();

    if (

$entity instanceof EntityInterface && $entity->getType() == 'tovar') {
      
$values = [];

      

// Получаем все значения свойств у вариаций для ноды
      
$q = \Drupal::database()->select('oc_pv_parameters''f1');
      
$q->fields('f1', ['pv_id''value']);     
      
$q->condition('f1.nid'$entity->id());
      
$res $q->execute();
      
      while(
$rec $res->fetchAssoc()){

        

$pattern '/^[EЕ]{1}\d{1,5}(-){1}\d{1,5}$/msiu';
        if(
preg_match($pattern$rec['value'])){
          
$rec['value'] = str_replace('//'''$rec['value']);
          
$rec['value'] = str_replace(['E','Е'], ''$rec['value']);
          
$rec['value'] = str_replace('-'''$rec['value']);
        }
        
// Исключаем дубликаты записей
        
$values[$rec['pv_id']][$rec['value']] = $rec['value'];
      }    

      

$fields $this->getFieldsHelper()
        ->
filterForPropertyPath($item->getFields(), NULL'product_variants_search');
      foreach (
$fields as $field) {      
        foreach(
$values as $pv_id=>$value){          
          
$field->addValue(implode(' '$value));
        }
      }
    }
  }
}
?>

Комментарии

Аватар пользователя vlucas vlucas 11 сентября в 14:31

Зачем менять то что индексируете? Вы индексируете товар. Добавьте просто поле-характеристика

Аватар пользователя vlucas vlucas 11 сентября в 14:33

Если надо отобразить характеристики по которым нашёлся товар при переходе в него, я бы просто js разрулил - добавив бы к ссылкам соответствующие параметры а далее в самом товаре их обработал бы. Думаю не надо здесь лезть в search api

Аватар пользователя kosskren kosskren 11 сентября в 14:44

ссылки у меня формируются в поиске примерно такие "www.site.ru/product-1". Я хочу добавить к ссылке № параметра, так - "www.site.ru/product-1?id=100". Для этого мне и нужно при поиске получать не только ноду, но и номер параметра

Аватар пользователя kosskren kosskren 11 сентября в 14:55

так у меня нет этого параметра). мне его для начала нужно связать с search api, что бы search api мне его выдавал при поиске. про это вопрос и был.

Аватар пользователя vlucas vlucas 11 сентября в 14:56

так индексируйте эту характеристику - добавляйте поле, далее поиск/фасет - и будет вам эта характеристика, всё это можно программно или вьюсом

Аватар пользователя kosskren kosskren 11 сентября в 15:01

я характеристику индексирую. по характеристикам поиск работает, но я не могу получить номер характеристики. есть только номер ноды

Аватар пользователя kosskren kosskren 11 сентября в 15:37

нет, к полям отношение не имеет. если было бы поле, то я через интерфейс search api его добавил и проблем не было).

Аватар пользователя vlucas vlucas 11 сентября в 15:50

ну хорошо. Ты создал своё поле search api программно и его добавил в индекс, в результате получил в таблице строки вида:
сущность/значение_характеристики
это нормально. Потому что когда ты будешь искать по этой характеристики у тебя в URL будет что-то вроде:
search?keywords=значение
Так вот и подставляй js эти параметры ?keywords=значение к URl товара на странице выдачи, а уже когда перешёл на страницу самого товара - обрабатывай их, хоть в контроллере

Аватар пользователя kosskren kosskren 11 сентября в 16:02

как-то костыльно это выглядит. уверен, что можно без js обойтись, должна быть возможность связать номер характеристики с search api. пока не могу понять как. если сам разберусь, то выложу тут решение или может, кто подскажет еще)

Аватар пользователя vlucas vlucas 11 сентября в 16:03

А где костыль?
Как раз то что вы делаете - это костыль.
Почему все думают что js - это костыль?

Аватар пользователя kosskren kosskren 11 сентября в 16:20

ну вот, начинаем костылями мериться)). про костыль вам не в обиду было сказано, не принимайте на свой счет.

js за костыль не считаю, но в конкретно в этом случае это не самое лучшее решение. search api мощный модуль, работаю с ним буквально пару недель. уверен, что просто не до конца понимаю его. по этому и задал тут вопрос

Аватар пользователя vlucas vlucas 11 сентября в 16:24

Да я не принял. ))
Ну уж если вы говорите костыльно, то тогда аргументируйте: дайте кейс где это вылезет в костыль?

Как раз в этой задаче - это самое разумное решение.
Да и СЕОшники, думаю, вам за него спасибо скажут )

Аватар пользователя vlucas vlucas 11 сентября в 16:08

я вот не пойму, а что даст вам связь номера характеристики с search api? Вам же всё равно надо будет в товар передать её? А как передавать то собираетесь?