Commit d4a0f50f authored by Bert Balcaen's avatar Bert Balcaen
Browse files

Initial commit

parents
This diff is collapsed.
# Credits
Based on https://github.com/grey-dev-0/laravel-scout-solr.
# Installing
```
php artisan vendor:publish GreyDev\LaravelSolr\SolrServiceProvider
```
# Laravel Solr Integration
This is a Laravel scout driver for Solr search engine, so that you can search Eloquent models through Solr, just in the same way explained in [Laravel Scout documentation](https://laravel.com/docs/5.3/scout) for any other Scout engine.
Besides the capability to interact with Solr outside of Laravel Scout scope if needed e.g. working with entities that are not stored in database and have no Eloquent models representing them.
## IMPORTANT
This package is still "Work In Progress" nevertheless, if you have a suggestion or have found a problem don't hesitate to contact me at [mo7y.66@gmail.com](mailto:mo7y.66@gmail.com) or open an issue.
{
"name": "grey-dev-0/laravel-scout-solr",
"description": "Solr driver for Laravel Scout",
"keywords": ["solr", "laravel-scout", "scout"],
"license": "GPL-3.0",
"require": {
"laravel/scout": "~4.0|~3.0|~2.0",
"solarium/solarium": "4.0.0-beta-1"
},
"autoload": {
"psr-4": {
"GreyDev\\LaravelSolr\\": "src/"
}
},
"extra": {
"laravel": {
"providers": [
"GreyDev\\LaravelSolr\\SolrServiceProvider",
"GreyDev\\LaravelSolr\\ScoutServiceProvider"
],
"aliases": {
"Solr": "GreyDev\\LaravelSolr\\SolrFacade"
}
}
}
}
<?php namespace GreyDev\LaravelSolr;
use Illuminate\Support\ServiceProvider;
use Laravel\Scout\EngineManager;
class ScoutServiceProvider extends ServiceProvider{
public function boot(){
resolve(EngineManager::class)->extend('solr', function () {
return new SolrEngine();
});
}
}
\ No newline at end of file
<?php namespace GreyDev\LaravelSolr;
use Laravel\Scout\Searchable as ScoutSearchable;
trait Searchable{
use ScoutSearchable;
/**
* Generates Eloquent attributes to Solr fields mapping.
*
* @return array
*/
public function getScoutMap(){
return array_combine($this->attributes, $this->attributes);
}
/**
* Get the indexable data array for the model.
*
* @return array
*/
public function toSearchableArray(){
$attributes = $this->toArray();
$map = $this->getScoutMap();
foreach ($attributes as $attribute => &$value) {
if($attribute == 'id')
$value = $this->getTable()."-$value";
if($attribute == $map[$attribute])
continue;
$attributes[$map[$attribute]] = $value;
unset($attributes[$attribute]);
}
return $attributes;
}
}
\ No newline at end of file
<?php namespace GreyDev\LaravelSolr;
use Illuminate\Database\Eloquent\Collection;
use Laravel\Scout\Builder;
use Laravel\Scout\Engines\Engine;
class SolrEngine extends Engine{
/**
* Update the given model in the index.
*
* @param \Illuminate\Database\Eloquent\Collection $models
* @throws \Exception In case of update command failure.
* @return void
*/
public function update($models){
$update = \Solr::createUpdate();
$models->each(function($model) use(&$update){
$document = $update->createDocument($model->toSearchableArray());
$update->addDocument($document);
});
$this->executeStatement($update);
}
/**
* Remove the given model from the index.
*
* @param \Illuminate\Database\Eloquent\Collection $models
* @throws \Exception In case of delete command failure.
* @return void
*/
public function delete($models){
$update = \Solr::createUpdate();
$models->each(function($model) use(&$update){
$update->addDeleteById($model->getKey());
});
$this->executeStatement($update);
}
/**
* Execute Update or Delete statement on the index.
*
* @throws \Exception In case of command failure.
* @param $statement \Solarium\QueryType\Update\Query\Query
*/
private function executeStatement(&$statement){
$statement->addCommit();
$response = \Solr::update($statement);
if($response->getStatus() != 0)
throw new \Exception("Update command failed \n\n".json_encode($response->getData()));
}
/**
* Perform the given search on the engine.
*
* @param \Laravel\Scout\Builder $builder
* @return mixed
*/
public function search(Builder $builder){
$query = \Solr::createSelect();
return $this->executeQuery($query, $builder);
}
/**
* Perform the given search on the engine.
*
* @param \Laravel\Scout\Builder $builder
* @param int $perPage
* @param int $page
* @return mixed
*/
public function paginate(Builder $builder, $perPage, $page){
$query = \Solr::createSelect();
$offset = ($page - 1) * $perPage;
return $this->executeQuery($query, $builder, $offset, $perPage);
}
/**
* Execute Select command on the index.
*
* @param \Solarium\QueryType\Select\Query\Query $query
* @param \Laravel\Scout\Builder $builder
* @param int $offset
* @param int $limit
* @return \Solarium\QueryType\Select\Result\Result
*/
private function executeQuery(&$query, &$builder, $offset = 0, $limit = null){
$conditions = (!empty($builder->query))? [$builder->query] : [];
foreach($builder->wheres as $key => &$value)
$conditions[] = "$key:\"$value\"";
$query->setQuery(implode(' ', $conditions));
if(!is_null($limit))
$query->setStart($offset)->setRows($limit);
return \Solr::select($query);
}
/**
* Pluck and return the primary keys of the given results.
*
* @param \Solarium\QueryType\Select\Result\Result $results
* @return \Illuminate\Support\Collection
*/
public function mapIds($results){
$ids = [];
foreach($results as $document)
$ids[] = $document->id;
return collect($ids);
}
/**
* Map the given results to instances of the given model.
*
* @param \Solarium\QueryType\Select\Result\Result $results
* @param \Illuminate\Database\Eloquent\Model $model
* @return \Illuminate\Database\Eloquent\Collection
*/
public function map($results, $model){
$map = array_flip($model->getScoutMap());
$models = [];
$modelClass = get_class($model);
foreach($results as $document){
$attributes = [];
foreach($document as $field => $value)
$attributes[$map[$field]] = ($map[$field] != 'id')? $value : str_replace($model->getTable().'-', '', $value);
$models[] = new $modelClass($attributes);
}
return Collection::make($models);
}
/**
* Get the total count from a raw result returned by the engine.
*
* @param \Solarium\QueryType\Select\Result\Result $results
* @return int
*/
public function getTotalCount($results){
return $results->getNumFound();
}
}
\ No newline at end of file
<?php namespace GreyDev\LaravelSolr;
use Illuminate\Support\Facades\Facade;
use Solarium\Client;
class SolrFacade extends Facade{
protected static function getFacadeAccessor(){
return Client::class;
}
}
\ No newline at end of file
<?php namespace GreyDev\LaravelSolr;
use Illuminate\Support\ServiceProvider;
use Solarium\Client;
class SolrServiceProvider extends ServiceProvider{
protected $defer = true;
public function boot(){
$this->publishes([
__DIR__.'/solr-config.php' => config_path('solr.php')
]);
}
public function register(){
$this->app->singleton(Client::class, function(){
return new Client(config('solr'));
});
}
public function provides(){
return [Client::class];
}
}
\ No newline at end of file
<?php
return [
'endpoint' => [
'localhost' => [
'host' => '127.0.0.1',
'port' => 8983,
'path' => '/solr/',
]
]
];
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment