Installation:
composer require baks-dev/search-redis
Ensure redis-stack-server is installed and configured (see REDIS.md).
Configure Redis Stack:
Edit /opt/redis-stack/etc/redis-stack.conf:
port 6579
daemonize no
requirepass your_secure_password
Restart Redis Stack:
sudo systemctl restart redis-stack-server
Environment Setup:
Add to .env:
REDIS_SEARCH_HOST=localhost
REDIS_SEARCH_PORT=6579
REDIS_SEARCH_PASSWORD=your_secure_password
REDIS_SEARCH_TABLE=1 # Optional: Defaults to 0
First Use Case:
Index a model (e.g., Product) via Artisan:
php artisan baks:search:redis:index Product
Verify with Redis CLI:
redis-cli -p 6579
127.0.0.1:6579> AUTH your_secure_password
127.0.0.1:6579> FT.SEARCH products * RETURN 2
Indexing Models:
baks:search:redis:index Artisan command to index Eloquent models:
php artisan baks:search:redis:index Product --fields=name,description,price
--fields to specify searchable fields (default: all non-relationship fields).--chunk=1000 to process in batches.Searching:
use BaksDev\SearchRedis\Facades\SearchRedis;
$results = SearchRedis::search('Product', 'laptop')->get();
$results = SearchRedis::search('Product')
->text('laptop')
->filter('price', ['>', 500])
->sortBy('price', 'desc')
->limit(10)
->get();
$results = SearchRedis::search('Product')->paginate(10);
Schema Management:
php artisan baks:search:redis:schema Product
php artisan baks:search:redis:drop Product
Real-Time Updates:
use BaksDev\SearchRedis\Observers\SearchRedisObserver;
Product::observe(SearchRedisObserver::class);
$product = Product::find(1);
SearchRedis::sync($product); // Updates index on save
Integration with Laravel Scout:
searchableAs in your model:
public function searchableAs()
{
return 'products'; // Custom index name
}
SearchRedisEngine:
use BaksDev\SearchRedis\Scout\SearchRedisEngine;
class Product extends Model
{
public function toSearchableArray()
{
return ['name', 'description'];
}
public function shouldBeSearchable()
{
return true;
}
}
Redis Stack Compatibility:
FT.SEARCH not found → Redis Stack not running or misconfigured.redis-cli -p 6579 FT._LIST (should return 1) "products" or similar).Field Mapping:
TEXT tag in schema.php artisan baks:search:redis:schema Product --fields="name:TEXT,description:TEXT,price:NUMERIC"
Password Authentication:
REDIS_SEARCH_PASSWORD in .env → Silent failures.redis-cli -p 6579 AUTH your_password
Index Naming Collisions:
model_name)..env or via searchableAs().Large Datasets:
--chunk=500 and run in queue jobs:
SearchRedis::index(Product::query(), 500);
Schema Inspection:
redis-cli -p 6579 FT._INFO products
SCHEMA field for field definitions.Query Logging:
Enable debug mode in .env:
REDIS_SEARCH_DEBUG=true
storage/logs/redis-search.log.Common Errors:
IndexNotFound: Run php artisan baks:search:redis:schema ModelName.FieldNotFound: Verify field names match the schema (case-sensitive).Custom Scoring:
Override SearchRedis facade to add custom scoring:
SearchRedis::search('Product')->addScoring('popularity', 0.5);
Pre/Post-Index Hooks:
Extend the SearchRedisObserver:
namespace App\Observers;
use BaksDev\SearchRedis\Observers\SearchRedisObserver;
use App\Models\Product;
class CustomSearchObserver extends SearchRedisObserver
{
public function saving(Product $model)
{
// Pre-index logic
}
public function saved(Product $model)
{
// Post-index logic
}
}
Multi-Tenant Indexing: Dynamically set index names based on tenant:
SearchRedis::setIndexName('products_' . auth()->id());
Async Indexing: Use Laravel Queues to defer indexing:
SearchRedis::queueSync($model); // Dispatches a job
ShouldQueue in the observer.Hybrid Search: Combine with Laravel Scout for fallback:
if (!SearchRedis::isAvailable()) {
return $model->search($query);
}
How can I help you explore Laravel packages today?