From aae7678ceaf63d00cd988ad15cec129bab448a5f Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Thu, 4 Jun 2015 11:11:56 +0930 Subject: [PATCH] Really rough fulltext driver implementation --- .../2015_02_24_000000_create_posts_table.php | 7 ++++--- src/Core/CoreServiceProvider.php | 5 +++++ .../Repositories/EloquentPostRepository.php | 19 +++++++++++++++---- .../Discussions/Fulltext/DriverInterface.php | 6 ++++++ .../Fulltext/MySqlFulltextDriver.php | 13 +++++++++++++ 5 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 src/Core/Search/Discussions/Fulltext/DriverInterface.php create mode 100644 src/Core/Search/Discussions/Fulltext/MySqlFulltextDriver.php diff --git a/migrations/2015_02_24_000000_create_posts_table.php b/migrations/2015_02_24_000000_create_posts_table.php index d5ab988e2..b172f342e 100644 --- a/migrations/2015_02_24_000000_create_posts_table.php +++ b/migrations/2015_02_24_000000_create_posts_table.php @@ -2,6 +2,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; +use DB; class CreatePostsTable extends Migration { @@ -14,7 +15,6 @@ class CreatePostsTable extends Migration public function up() { Schema::create('posts', function (Blueprint $table) { - $table->increments('id'); $table->integer('discussion_id')->unsigned(); $table->integer('number')->unsigned()->nullable(); @@ -29,10 +29,11 @@ class CreatePostsTable extends Migration $table->integer('edit_user_id')->unsigned()->nullable(); $table->dateTime('hide_time')->nullable(); $table->integer('hide_user_id')->unsigned()->nullable(); + + $table->unique(['discussion_id', 'number']); }); - // add fulltext index to content (and title?) - // add unique index on [discussion_id, number] !!! + DB::statement('ALTER TABLE posts ADD FULLTEXT content (content)'); } /** diff --git a/src/Core/CoreServiceProvider.php b/src/Core/CoreServiceProvider.php index 55833f4f1..5556a18f7 100644 --- a/src/Core/CoreServiceProvider.php +++ b/src/Core/CoreServiceProvider.php @@ -89,6 +89,11 @@ class CoreServiceProvider extends ServiceProvider 'Flarum\Core\Repositories\EloquentActivityRepository' ); + $this->app->bind( + 'Flarum\Core\Search\Discussions\Fulltext\DriverInterface', + 'Flarum\Core\Search\Discussions\Fulltext\MySqlFulltextDriver' + ); + $avatarFilesystem = function (Container $app) { return $app->make('Illuminate\Contracts\Filesystem\Factory')->disk('flarum-avatars')->getDriver(); }; diff --git a/src/Core/Repositories/EloquentPostRepository.php b/src/Core/Repositories/EloquentPostRepository.php index 886e0a415..b08d12ffb 100644 --- a/src/Core/Repositories/EloquentPostRepository.php +++ b/src/Core/Repositories/EloquentPostRepository.php @@ -3,9 +3,17 @@ use Illuminate\Database\Eloquent\Builder; use Flarum\Core\Models\Post; use Flarum\Core\Models\User; +use Flarum\Core\Search\Discussions\Fulltext\DriverInterface; class EloquentPostRepository implements PostRepositoryInterface { + protected $fulltext; + + public function __construct(DriverInterface $fulltext) + { + $this->fulltext = $fulltext; + } + /** * Find a post by ID, optionally making sure it is visible to a certain * user, or throw an exception. @@ -72,10 +80,13 @@ class EloquentPostRepository implements PostRepositoryInterface */ public function findByContent($string, User $user = null) { - $query = Post::select('id', 'discussion_id') - ->where('content', 'like', '%'.$string.'%'); - // ->whereRaw('MATCH (`content`) AGAINST (? IN BOOLEAN MODE)', [$string]) - // ->orderByRaw('MATCH (`content`) AGAINST (?) DESC', [$string]) + $ids = $this->fulltext->match($string); + + $query = Post::select('id', 'discussion_id')->whereIn('id', $ids); + + foreach ($ids as $id) { + $query->orderByRaw('id != ?', [$id]); + } return $this->scopeVisibleForUser($query, $user)->get(); } diff --git a/src/Core/Search/Discussions/Fulltext/DriverInterface.php b/src/Core/Search/Discussions/Fulltext/DriverInterface.php new file mode 100644 index 000000000..a80c6f07f --- /dev/null +++ b/src/Core/Search/Discussions/Fulltext/DriverInterface.php @@ -0,0 +1,6 @@ +orderByRaw('MATCH (`content`) AGAINST (?) DESC', [$string]) + ->lists('id'); + } +}