diff --git a/.env.example b/.env.example index b09beb1..e9d40e9 100644 --- a/.env.example +++ b/.env.example @@ -14,3 +14,6 @@ CACHE_DRIVER=file QUEUE_CONNECTION=sync SESSION_DRIVER=file SESSION_LIFETIME=120 + +SCOUT_DRIVER=tntsearch +TNTSEARCH_FUZZINESS=true diff --git a/.phpstorm.meta.php b/.phpstorm.meta.php index 160ff33..369f55b 100644 --- a/.phpstorm.meta.php +++ b/.phpstorm.meta.php @@ -55,6 +55,7 @@ namespace PHPSTORM_META { 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, + 'Laravel\Scout\EngineManager' => \Laravel\Scout\EngineManager::class, 'Neomerx\JsonApi\Contracts\Encoder\Parameters\EncodingParametersInterface' => \CloudCreativity\LaravelJsonApi\Encoder\Parameters\EncodingParameters::class, 'Neomerx\JsonApi\Contracts\Http\Headers\HeaderParametersInterface' => \Neomerx\JsonApi\Http\Headers\HeaderParameters::class, 'NunoMaduro\Collision\Contracts\Provider' => \NunoMaduro\Collision\Provider::class, @@ -235,6 +236,7 @@ namespace PHPSTORM_META { 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, + 'Laravel\Scout\EngineManager' => \Laravel\Scout\EngineManager::class, 'Neomerx\JsonApi\Contracts\Encoder\Parameters\EncodingParametersInterface' => \CloudCreativity\LaravelJsonApi\Encoder\Parameters\EncodingParameters::class, 'Neomerx\JsonApi\Contracts\Http\Headers\HeaderParametersInterface' => \Neomerx\JsonApi\Http\Headers\HeaderParameters::class, 'NunoMaduro\Collision\Contracts\Provider' => \NunoMaduro\Collision\Provider::class, @@ -415,6 +417,7 @@ namespace PHPSTORM_META { 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, + 'Laravel\Scout\EngineManager' => \Laravel\Scout\EngineManager::class, 'Neomerx\JsonApi\Contracts\Encoder\Parameters\EncodingParametersInterface' => \CloudCreativity\LaravelJsonApi\Encoder\Parameters\EncodingParameters::class, 'Neomerx\JsonApi\Contracts\Http\Headers\HeaderParametersInterface' => \Neomerx\JsonApi\Http\Headers\HeaderParameters::class, 'NunoMaduro\Collision\Contracts\Provider' => \NunoMaduro\Collision\Provider::class, @@ -595,6 +598,7 @@ namespace PHPSTORM_META { 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, + 'Laravel\Scout\EngineManager' => \Laravel\Scout\EngineManager::class, 'Neomerx\JsonApi\Contracts\Encoder\Parameters\EncodingParametersInterface' => \CloudCreativity\LaravelJsonApi\Encoder\Parameters\EncodingParameters::class, 'Neomerx\JsonApi\Contracts\Http\Headers\HeaderParametersInterface' => \Neomerx\JsonApi\Http\Headers\HeaderParameters::class, 'NunoMaduro\Collision\Contracts\Provider' => \NunoMaduro\Collision\Provider::class, @@ -775,6 +779,7 @@ namespace PHPSTORM_META { 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, + 'Laravel\Scout\EngineManager' => \Laravel\Scout\EngineManager::class, 'Neomerx\JsonApi\Contracts\Encoder\Parameters\EncodingParametersInterface' => \CloudCreativity\LaravelJsonApi\Encoder\Parameters\EncodingParameters::class, 'Neomerx\JsonApi\Contracts\Http\Headers\HeaderParametersInterface' => \Neomerx\JsonApi\Http\Headers\HeaderParameters::class, 'NunoMaduro\Collision\Contracts\Provider' => \NunoMaduro\Collision\Provider::class, @@ -955,6 +960,7 @@ namespace PHPSTORM_META { 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, + 'Laravel\Scout\EngineManager' => \Laravel\Scout\EngineManager::class, 'Neomerx\JsonApi\Contracts\Encoder\Parameters\EncodingParametersInterface' => \CloudCreativity\LaravelJsonApi\Encoder\Parameters\EncodingParameters::class, 'Neomerx\JsonApi\Contracts\Http\Headers\HeaderParametersInterface' => \Neomerx\JsonApi\Http\Headers\HeaderParameters::class, 'NunoMaduro\Collision\Contracts\Provider' => \NunoMaduro\Collision\Provider::class, @@ -1135,6 +1141,7 @@ namespace PHPSTORM_META { 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, + 'Laravel\Scout\EngineManager' => \Laravel\Scout\EngineManager::class, 'Neomerx\JsonApi\Contracts\Encoder\Parameters\EncodingParametersInterface' => \CloudCreativity\LaravelJsonApi\Encoder\Parameters\EncodingParameters::class, 'Neomerx\JsonApi\Contracts\Http\Headers\HeaderParametersInterface' => \Neomerx\JsonApi\Http\Headers\HeaderParameters::class, 'NunoMaduro\Collision\Contracts\Provider' => \NunoMaduro\Collision\Provider::class, @@ -1315,6 +1322,7 @@ namespace PHPSTORM_META { 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, + 'Laravel\Scout\EngineManager' => \Laravel\Scout\EngineManager::class, 'Neomerx\JsonApi\Contracts\Encoder\Parameters\EncodingParametersInterface' => \CloudCreativity\LaravelJsonApi\Encoder\Parameters\EncodingParameters::class, 'Neomerx\JsonApi\Contracts\Http\Headers\HeaderParametersInterface' => \Neomerx\JsonApi\Http\Headers\HeaderParameters::class, 'NunoMaduro\Collision\Contracts\Provider' => \NunoMaduro\Collision\Provider::class, @@ -1495,6 +1503,7 @@ namespace PHPSTORM_META { 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, + 'Laravel\Scout\EngineManager' => \Laravel\Scout\EngineManager::class, 'Neomerx\JsonApi\Contracts\Encoder\Parameters\EncodingParametersInterface' => \CloudCreativity\LaravelJsonApi\Encoder\Parameters\EncodingParameters::class, 'Neomerx\JsonApi\Contracts\Http\Headers\HeaderParametersInterface' => \Neomerx\JsonApi\Http\Headers\HeaderParameters::class, 'NunoMaduro\Collision\Contracts\Provider' => \NunoMaduro\Collision\Provider::class, @@ -1675,6 +1684,7 @@ namespace PHPSTORM_META { 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, + 'Laravel\Scout\EngineManager' => \Laravel\Scout\EngineManager::class, 'Neomerx\JsonApi\Contracts\Encoder\Parameters\EncodingParametersInterface' => \CloudCreativity\LaravelJsonApi\Encoder\Parameters\EncodingParameters::class, 'Neomerx\JsonApi\Contracts\Http\Headers\HeaderParametersInterface' => \Neomerx\JsonApi\Http\Headers\HeaderParameters::class, 'NunoMaduro\Collision\Contracts\Provider' => \NunoMaduro\Collision\Provider::class, @@ -1855,6 +1865,7 @@ namespace PHPSTORM_META { 'Illuminate\Notifications\ChannelManager' => \Illuminate\Notifications\ChannelManager::class, 'Illuminate\Routing\Contracts\ControllerDispatcher' => \Illuminate\Routing\ControllerDispatcher::class, 'Illuminate\Session\Middleware\StartSession' => \Illuminate\Session\Middleware\StartSession::class, + 'Laravel\Scout\EngineManager' => \Laravel\Scout\EngineManager::class, 'Neomerx\JsonApi\Contracts\Encoder\Parameters\EncodingParametersInterface' => \CloudCreativity\LaravelJsonApi\Encoder\Parameters\EncodingParameters::class, 'Neomerx\JsonApi\Contracts\Http\Headers\HeaderParametersInterface' => \Neomerx\JsonApi\Http\Headers\HeaderParameters::class, 'NunoMaduro\Collision\Contracts\Provider' => \NunoMaduro\Collision\Provider::class, diff --git a/_ide_helper.php b/_ide_helper.php index 2288cce..1d05ee7 100644 --- a/_ide_helper.php +++ b/_ide_helper.php @@ -14947,6 +14947,28 @@ } +} + + namespace Laravel\Scout { + /** + * + * + */ + class Builder { + /** + * + * + * @see \TeamTNT\Scout\TNTSearchScoutServiceProvider::boot() + * @param mixed $constraints + * @static + */ + public static function constrain($constraints) + { + return \Laravel\Scout\Builder::constrain($constraints); + } + + } + } diff --git a/app/Http/Controllers/IngredientPickerController.php b/app/Http/Controllers/IngredientPickerController.php index ebe4a89..1c8186b 100644 --- a/app/Http/Controllers/IngredientPickerController.php +++ b/app/Http/Controllers/IngredientPickerController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers; use App\Models\Food; use App\Models\Recipe; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -14,12 +15,12 @@ class IngredientPickerController extends Controller */ public function search(Request $request): JsonResponse { - $results = []; + $results = new Collection(); $term = $request->query->get('term'); if (!empty($term)) { - $results = Food::search($term); - $results = $results->merge(Recipe::search($term)); + $results = $results->merge(Food::search($term)->get()); + $results = $results->merge(Recipe::search($term)->get()); } - return response()->json($results); + return response()->json($results->sortBy('name')->values()); } } diff --git a/app/Models/Food.php b/app/Models/Food.php index 145c681..bd6378c 100644 --- a/app/Models/Food.php +++ b/app/Models/Food.php @@ -8,7 +8,7 @@ use App\Models\Traits\Sluggable; use App\Support\Number; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\Relations\HasMany; +use Laravel\Scout\Searchable; use Spatie\Tags\HasTags; /** @@ -30,8 +30,18 @@ use Spatie\Tags\HasTags; * @property float $protein * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at + * @property string|null $source + * @property string|null $notes + * @property string|null $serving_unit_name + * @property-read string $serving_size_formatted + * @property-read string|null $serving_unit_formatted + * @property-read string $type + * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\IngredientAmount[] $ingredientAmountRelationships + * @property-read int|null $ingredient_amount_relationships_count * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\JournalEntry[] $journalEntries * @property-read int|null $journal_entries_count + * @property \Illuminate\Database\Eloquent\Collection|\Spatie\Tags\Tag[] $tags + * @property-read int|null $tags_count * @method static \Illuminate\Database\Eloquent\Builder|Food findSimilarSlugs(string $attribute, array $config, string $slug) * @method static \Illuminate\Database\Eloquent\Builder|Food newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|Food newQuery() @@ -45,37 +55,25 @@ use Spatie\Tags\HasTags; * @method static \Illuminate\Database\Eloquent\Builder|Food whereFat($value) * @method static \Illuminate\Database\Eloquent\Builder|Food whereId($value) * @method static \Illuminate\Database\Eloquent\Builder|Food whereName($value) + * @method static \Illuminate\Database\Eloquent\Builder|Food whereNotes($value) * @method static \Illuminate\Database\Eloquent\Builder|Food whereProtein($value) * @method static \Illuminate\Database\Eloquent\Builder|Food whereServingSize($value) * @method static \Illuminate\Database\Eloquent\Builder|Food whereServingUnit($value) + * @method static \Illuminate\Database\Eloquent\Builder|Food whereServingUnitName($value) * @method static \Illuminate\Database\Eloquent\Builder|Food whereServingWeight($value) * @method static \Illuminate\Database\Eloquent\Builder|Food whereSlug($value) * @method static \Illuminate\Database\Eloquent\Builder|Food whereSodium($value) + * @method static \Illuminate\Database\Eloquent\Builder|Food whereSource($value) * @method static \Illuminate\Database\Eloquent\Builder|Food whereUpdatedAt($value) - * @mixin \Eloquent - * @property-read string $serving_size_formatted - * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\IngredientAmount[] $ingredientAmounts - * @property-read int|null $ingredient_amounts_count - * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\IngredientAmount[] $ingredientAmountRelationships - * @property-read int|null $ingredient_amount_relationships_count - * @property-read string $type - * @property \Illuminate\Database\Eloquent\Collection|\Spatie\Tags\Tag[] $tags - * @property-read int|null $tags_count * @method static \Illuminate\Database\Eloquent\Builder|Food withAllTags($tags, ?string $type = null) * @method static \Illuminate\Database\Eloquent\Builder|Food withAllTagsOfAnyType($tags) * @method static \Illuminate\Database\Eloquent\Builder|Food withAnyTags($tags, ?string $type = null) * @method static \Illuminate\Database\Eloquent\Builder|Food withAnyTagsOfAnyType($tags) - * @property string|null $source - * @property string|null $notes - * @method static \Illuminate\Database\Eloquent\Builder|Food whereNotes($value) - * @method static \Illuminate\Database\Eloquent\Builder|Food whereSource($value) - * @property string|null $serving_unit_name - * @property-read string|null $serving_unit_formatted - * @method static \Illuminate\Database\Eloquent\Builder|Food whereServingUnitName($value) + * @mixin \Eloquent */ final class Food extends Model { - use HasFactory, HasTags, Ingredient, Journalable, Sluggable; + use HasFactory, HasTags, Ingredient, Journalable, Searchable, Sluggable; /** * @inheritdoc @@ -125,6 +123,21 @@ final class Food extends Model 'serving_unit_formatted' ]; + /** + * @inheritdoc + */ + public function toSearchableArray(): array + { + $this->tags; + return [ + 'id' => $this->id, + 'name' => $this->name, + 'detail' => $this->detail, + 'brand' => $this->brand, + 'tags' => $this->tags->pluck('name'), + ]; + } + /** * Get the serving size as a formatted string (e.g. 0.5 = 1/2). */ diff --git a/app/Models/Recipe.php b/app/Models/Recipe.php index 315b7fa..892d893 100644 --- a/app/Models/Recipe.php +++ b/app/Models/Recipe.php @@ -6,10 +6,10 @@ use App\Models\Traits\HasIngredients; use App\Models\Traits\Ingredient; use App\Models\Traits\Journalable; use App\Models\Traits\Sluggable; -use App\Support\Number; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; +use Laravel\Scout\Searchable; use Spatie\Tags\HasTags; /** @@ -23,10 +23,19 @@ use Spatie\Tags\HasTags; * @property \Illuminate\Support\Carbon|null $updated_at * @property string|null $description * @property string|null $source + * @property float|null $weight + * @property-read float|null $serving_weight + * @property-read string $type + * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\IngredientAmount[] $ingredientAmountRelationships + * @property-read int|null $ingredient_amount_relationships_count + * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\IngredientAmount[] $ingredientAmounts + * @property-read int|null $ingredient_amounts_count * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\JournalEntry[] $journalEntries * @property-read int|null $journal_entries_count + * @property \Illuminate\Database\Eloquent\Collection|\Spatie\Tags\Tag[] $tags * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\RecipeStep[] $steps * @property-read int|null $steps_count + * @property-read int|null $tags_count * @method static \Illuminate\Database\Eloquent\Builder|Recipe findSimilarSlugs(string $attribute, array $config, string $slug) * @method static \Illuminate\Database\Eloquent\Builder|Recipe newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|Recipe newQuery() @@ -39,27 +48,16 @@ use Spatie\Tags\HasTags; * @method static \Illuminate\Database\Eloquent\Builder|Recipe whereSlug($value) * @method static \Illuminate\Database\Eloquent\Builder|Recipe whereSource($value) * @method static \Illuminate\Database\Eloquent\Builder|Recipe whereUpdatedAt($value) - * @mixin \Eloquent - * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\IngredientAmount[] $ingredientAmounts - * @property-read int|null $ingredient_amounts_count - * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\IngredientAmount[] $ingredients - * @property-read int|null $ingredients_count - * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\IngredientAmount[] $ingredientAmountRelationships - * @property-read int|null $ingredient_amount_relationships_count - * @property-read string $type - * @property \Illuminate\Database\Eloquent\Collection|\Spatie\Tags\Tag[] $tags - * @property-read int|null $tags_count + * @method static \Illuminate\Database\Eloquent\Builder|Recipe whereWeight($value) * @method static \Illuminate\Database\Eloquent\Builder|Recipe withAllTags($tags, ?string $type = null) * @method static \Illuminate\Database\Eloquent\Builder|Recipe withAllTagsOfAnyType($tags) * @method static \Illuminate\Database\Eloquent\Builder|Recipe withAnyTags($tags, ?string $type = null) * @method static \Illuminate\Database\Eloquent\Builder|Recipe withAnyTagsOfAnyType($tags) - * @property float|null $weight - * @property-read float|null $serving_weight - * @method static \Illuminate\Database\Eloquent\Builder|Recipe whereWeight($value) + * @mixin \Eloquent */ final class Recipe extends Model { - use HasFactory, HasIngredients, HasTags, Ingredient, Journalable, Sluggable; + use HasFactory, HasIngredients, HasTags, Ingredient, Journalable, Searchable, Sluggable; /** * @inheritdoc @@ -99,6 +97,20 @@ final class Recipe extends Model 'serving_weight', ]; + /** + * @inheritdoc + */ + public function toSearchableArray(): array + { + $this->tags; + return [ + 'id' => $this->id, + 'name' => $this->name, + 'source' => $this->source, + 'tags' => $this->tags->pluck('name'), + ]; + } + /** * Get the serving weight (rounded). */ diff --git a/app/Models/Traits/Ingredient.php b/app/Models/Traits/Ingredient.php index 36bce94..67e4d4b 100644 --- a/app/Models/Traits/Ingredient.php +++ b/app/Models/Traits/Ingredient.php @@ -30,11 +30,4 @@ trait Ingredient public function ingredientAmountRelationships(): MorphMany { return $this->morphMany(IngredientAmount::class, 'ingredient')->with('parent'); } - - /** - * Get search results for a term. - */ - public static function search(string $term, int $limit = 10): Collection { - return (new static)::where('name', 'like', "%{$term}%")->limit($limit)->get(); - } } diff --git a/composer.json b/composer.json index 20c1885..0f45ce9 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,8 @@ "laravel/framework": "^8.12", "laravel/tinker": "^2.5", "phospr/fraction": "^1.2", - "spatie/laravel-tags": "^3.0" + "spatie/laravel-tags": "^3.0", + "teamtnt/laravel-scout-tntsearch-driver": "^11.1" }, "require-dev": { "barryvdh/laravel-ide-helper": "^2.9", diff --git a/composer.lock b/composer.lock index c568835..22ad09d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7b4bf3adf3d57d7b218fd422cc1e50a9", + "content-hash": "f8b6c15824ff4be21313cc1abc4ae9ad", "packages": [ { "name": "asm89/stack-cors", @@ -1291,6 +1291,75 @@ }, "time": "2020-12-22T21:21:19+00:00" }, + { + "name": "laravel/scout", + "version": "v8.6.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/scout.git", + "reference": "54070f7b68fed15f25e61e68884c4110496b8aa1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/scout/zipball/54070f7b68fed15f25e61e68884c4110496b8aa1", + "reference": "54070f7b68fed15f25e61e68884c4110496b8aa1", + "shasum": "" + }, + "require": { + "illuminate/bus": "^6.0|^7.0|^8.0", + "illuminate/contracts": "^6.0|^7.0|^8.0", + "illuminate/database": "^6.0|^7.0|^8.0", + "illuminate/http": "^6.0|^7.0|^8.0", + "illuminate/pagination": "^6.0|^7.0|^8.0", + "illuminate/queue": "^6.0|^7.0|^8.0", + "illuminate/support": "^6.0|^7.0|^8.0", + "php": "^7.2|^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^8.0|^9.3" + }, + "suggest": { + "algolia/algoliasearch-client-php": "Required to use the Algolia engine (^2.2)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "8.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Scout\\ScoutServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Scout\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel Scout provides a driver based solution to searching your Eloquent models.", + "keywords": [ + "algolia", + "laravel", + "search" + ], + "support": { + "issues": "https://github.com/laravel/scout/issues", + "source": "https://github.com/laravel/scout" + }, + "time": "2021-01-19T15:30:52+00:00" + }, { "name": "laravel/tinker", "version": "v2.5.0", @@ -5415,6 +5484,154 @@ ], "time": "2020-12-16T17:02:19+00:00" }, + { + "name": "teamtnt/laravel-scout-tntsearch-driver", + "version": "v11.1.0", + "source": { + "type": "git", + "url": "https://github.com/teamtnt/laravel-scout-tntsearch-driver.git", + "reference": "a9c27a68dc2bd74fb354165633520de95708215d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/teamtnt/laravel-scout-tntsearch-driver/zipball/a9c27a68dc2bd74fb354165633520de95708215d", + "reference": "a9c27a68dc2bd74fb354165633520de95708215d", + "shasum": "" + }, + "require": { + "illuminate/bus": "~5.4|^6.0|^7.0|^8.0", + "illuminate/contracts": "~5.4|^6.0|^7.0|^8.0", + "illuminate/database": "~5.4|^6.0|^7.0|^8.0", + "illuminate/pagination": "~5.4|^6.0|^7.0|^8.0", + "illuminate/queue": "~5.4|^6.0|^7.0|^8.0", + "illuminate/support": "~5.4|^6.0|^7.0|^8.0", + "laravel/scout": "7.*|^8.0|^8.3", + "php": ">=7.1", + "teamtnt/tntsearch": "2.*" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^8.0|^9.3" + }, + "suggest": { + "teamtnt/tntsearch": "Required to use the TNTSearch engine." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + }, + "laravel": { + "providers": [ + "TeamTNT\\Scout\\TNTSearchScoutServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "TeamTNT\\Scout\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "TNT Studio", + "email": "info@tntstudio.hr" + } + ], + "description": "Driver for Laravel Scout search package based on https://github.com/teamtnt/tntsearch", + "keywords": [ + "laravel", + "scout", + "search", + "tntsearch" + ], + "support": { + "issues": "https://github.com/teamtnt/laravel-scout-tntsearch-driver/issues", + "source": "https://github.com/teamtnt/laravel-scout-tntsearch-driver/tree/v11.1.0" + }, + "time": "2020-11-11T11:17:48+00:00" + }, + { + "name": "teamtnt/tntsearch", + "version": "v2.6.0", + "source": { + "type": "git", + "url": "https://github.com/teamtnt/tntsearch.git", + "reference": "d9b2d764491c87f03ec214ed8dbc27336cf0c0e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/teamtnt/tntsearch/zipball/d9b2d764491c87f03ec214ed8dbc27336cf0c0e4", + "reference": "d9b2d764491c87f03ec214ed8dbc27336cf0c0e4", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "ext-pdo_sqlite": "*", + "ext-sqlite3": "*", + "php": "~7.1|^8" + }, + "require-dev": { + "phpunit/phpunit": "7.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "TeamTNT\\TNTSearch\\": "src" + }, + "files": [ + "helper/helpers.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nenad Tičarić", + "email": "nticaric@gmail.com", + "homepage": "http://www.tntstudio.us", + "role": "Developer" + } + ], + "description": "A fully featured full text search engine written in PHP", + "homepage": "https://github.com/teamtnt/tntsearch", + "keywords": [ + "Fuzzy search", + "bm25", + "fulltext", + "geosearch", + "search", + "stemming", + "teamtnt", + "text classification", + "tntsearch" + ], + "support": { + "issues": "https://github.com/teamtnt/tntsearch/issues", + "source": "https://github.com/teamtnt/tntsearch/tree/v2.6.0" + }, + "funding": [ + { + "url": "https://ko-fi.com/nticaric", + "type": "ko_fi" + }, + { + "url": "https://opencollective.com/tntsearch", + "type": "open_collective" + }, + { + "url": "https://www.patreon.com/nticaric", + "type": "patreon" + } + ], + "time": "2020-12-21T09:11:54+00:00" + }, { "name": "tijsverkoyen/css-to-inline-styles", "version": "2.2.3", diff --git a/config/app.php b/config/app.php index ed50340..e4b23ab 100644 --- a/config/app.php +++ b/config/app.php @@ -165,6 +165,8 @@ return [ /* * Package Service Providers... */ + Laravel\Scout\ScoutServiceProvider::class, + TeamTNT\Scout\TNTSearchScoutServiceProvider::class, /* * Application Service Providers... diff --git a/config/scout.php b/config/scout.php new file mode 100644 index 0000000..c28e0e4 --- /dev/null +++ b/config/scout.php @@ -0,0 +1,138 @@ + env('SCOUT_DRIVER', 'tntsearch'), + + /* + |-------------------------------------------------------------------------- + | Index Prefix + |-------------------------------------------------------------------------- + | + | Here you may specify a prefix that will be applied to all search index + | names used by Scout. This prefix may be useful if you have multiple + | "tenants" or applications sharing the same search infrastructure. + | + */ + + 'prefix' => env('SCOUT_PREFIX', ''), + + /* + |-------------------------------------------------------------------------- + | Queue Data Syncing + |-------------------------------------------------------------------------- + | + | This option allows you to control if the operations that sync your data + | with your search engines are queued. When this is set to "true" then + | all automatic data syncing will get queued for better performance. + | + */ + + 'queue' => env('SCOUT_QUEUE', false), + + /* + |-------------------------------------------------------------------------- + | Database Transactions + |-------------------------------------------------------------------------- + | + | This configuration option determines if your data will only be synced + | with your search indexes after every open database transaction has + | been committed, thus preventing any discarded data from syncing. + | + */ + + 'after_commit' => false, + + /* + |-------------------------------------------------------------------------- + | Chunk Sizes + |-------------------------------------------------------------------------- + | + | These options allow you to control the maximum chunk size when you are + | mass importing data into the search engine. This allows you to fine + | tune each of these chunk sizes based on the power of the servers. + | + */ + + 'chunk' => [ + 'searchable' => 500, + 'unsearchable' => 500, + ], + + /* + |-------------------------------------------------------------------------- + | Soft Deletes + |-------------------------------------------------------------------------- + | + | This option allows to control whether to keep soft deleted records in + | the search indexes. Maintaining soft deleted records can be useful + | if your application still needs to search for the records later. + | + */ + + 'soft_delete' => false, + + /* + |-------------------------------------------------------------------------- + | Identify User + |-------------------------------------------------------------------------- + | + | This option allows you to control whether to notify the search engine + | of the user performing the search. This is sometimes useful if the + | engine supports any analytics based on this application's users. + | + | Supported engines: "algolia" + | + */ + + 'identify' => env('SCOUT_IDENTIFY', false), + + /* + |-------------------------------------------------------------------------- + | Algolia Configuration + |-------------------------------------------------------------------------- + | + | Here you may configure your Algolia settings. Algolia is a cloud hosted + | search engine which works great with Scout out of the box. Just plug + | in your application ID and admin API key to get started searching. + | + */ + + 'algolia' => [ + 'id' => env('ALGOLIA_APP_ID', ''), + 'secret' => env('ALGOLIA_SECRET', ''), + ], + + /* + |-------------------------------------------------------------------------- + | TNT Search Configuration + |-------------------------------------------------------------------------- + */ + + 'tntsearch' => [ + 'storage' => storage_path() . '/indexes', + 'fuzziness' => env('TNTSEARCH_FUZZINESS', false), + 'fuzzy' => [ + 'prefix_length' => 2, + 'max_expansions' => 50, + 'distance' => 2 + ], + 'asYouType' => false, + 'searchBoolean' => env('TNTSEARCH_BOOLEAN', false), + 'maxDocs' => env('TNTSEARCH_MAX_DOCS', 500), + ], + +]; diff --git a/storage/indexes/.gitignore b/storage/indexes/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/indexes/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore