TNT Searchable Trait
<?php
use Illuminate\Database\Eloquent\Model;
use TeamTNT\TNTSearch\Facades\TNTSearch;
trait Searchable
{
/**
* Auto update search index using model events.
*
* @return void
*/
protected static function syncSearchableIndex()
{
if (config('services.tntsearch.sync') && ! app()->runningInConsole()) {
static::created([__CLASS__, 'insertToIndex']);
static::updated([__CLASS__, 'updateIndex']);
static::deleted([__CLASS__, 'deleteFromIndex']);
}
}
/**
* Dele a entity from the search index.
*
* @param \Illuminate\Database\Eloquent\Model $entity
*
* @return void
*/
public static function deleteFromIndex(Model $entity)
{
$entity->createIndexIfNotExists();
TNTSearch::selectIndex($entity->searchableAs());
$index = TNTSearch::getIndex();
$index->delete($entity->getPrimaryKeyColumn());
}
/**
* Update a entity in the search index.
*
* @param \Illuminate\Database\Eloquent\Model $entity
*
* @return void
*/
public static function updateIndex(Model $entity)
{
$entity->createIndexIfNotExists();
TNTSearch::selectIndex($entity->searchableAs());
$index = TNTSearch::getIndex();
$index->update($entity->getPrimaryKeyColumn(), $entity->toSearchableArray());
}
/**
* Insert a new entity in the search index.
*
* @param \Illuminate\Database\Eloquent\Model $entity
*
* @return void
*/
public static function insertToIndex(Model $entity)
{
$entity->createIndexIfNotExists();
TNTSearch::selectIndex($entity->searchableAs());
$index = TNTSearch::getIndex();
$index->insert($entity->toSearchableArray());
}
/**
* Create a new search index if doesn't exists one.
*
* @return void
*/
public function createIndexIfNotExists()
{
$indexFile = sprintf('%s/%s', config('services.tntsearch.storage'), $this->searchableAs());
if (! is_file($indexFile)) {
TNTSearch::createIndex($this->searchableAs());
}
}
/**
* Perform a search against the model's indexed data.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param string $search
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeSearch($builder, $query)
{
TNTSearch::selectIndex($this->searchableAs());
$results = TNTSearch::search($query, $this->count());
$ids = $results['ids'];
$column = $this->getPrimaryKeyColumn();
$orderByQuery = sprintf('FIELD (%s, %s)', $column, implode(', ', $ids));
return $builder->whereIn($column, $ids)->orderByRaw($orderByQuery);
}
/**
* Get the primary key column name.
*
* @return string
*/
private function getPrimaryKeyColumn()
{
return sprintf('%s.%s', $this->getTable(), $this->getKeyName());
}
/**
* Get the index name for the model.
*
* @return string
*/
public function searchableAs()
{
return sprintf('%s.index', strtolower(class_basename(get_called_class())));
}
/**
* Get the indexable data array for the model.
*
* @return array
*/
public function toSearchableArray()
{
return $this->toArray();
}
}