Skip to content

Commit bb7b9cd

Browse files
committed
wip
1 parent 0fb074a commit bb7b9cd

27 files changed

Lines changed: 1122 additions & 584 deletions

.github/workflows/run-tests.yml

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,52 @@ jobs:
2121
- 7700:7700
2222
options: --health-cmd "curl -f http://localhost:7700/health" --health-interval 2s --health-timeout 5s --health-retries 15
2323

24+
mysql:
25+
image: mysql:8
26+
env:
27+
MYSQL_ROOT_PASSWORD: password
28+
MYSQL_DATABASE: site_search_test
29+
ports:
30+
- 3306:3306
31+
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
32+
33+
postgres:
34+
image: postgres:16
35+
env:
36+
POSTGRES_USER: postgres
37+
POSTGRES_PASSWORD: password
38+
POSTGRES_DB: site_search_test
39+
ports:
40+
- 5432:5432
41+
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
42+
2443
strategy:
2544
fail-fast: false
2645
matrix:
2746
os: [ubuntu-latest]
2847
php: [8.5, 8.4]
2948
laravel: ['12.*', '13.*']
3049
stability: [prefer-stable]
50+
db: [sqlite]
3151
include:
3252
- laravel: 12.*
3353
testbench: 10.*
3454
- laravel: 13.*
3555
testbench: 11.*
56+
- os: ubuntu-latest
57+
php: '8.4'
58+
laravel: '12.*'
59+
testbench: '10.*'
60+
stability: prefer-stable
61+
db: mysql
62+
- os: ubuntu-latest
63+
php: '8.4'
64+
laravel: '12.*'
65+
testbench: '10.*'
66+
stability: prefer-stable
67+
db: pgsql
3668

37-
name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }}
69+
name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.db }} - ${{ matrix.stability }}
3870

3971
steps:
4072
- name: Checkout code
@@ -44,7 +76,7 @@ jobs:
4476
uses: shivammathur/setup-php@v2
4577
with:
4678
php-version: ${{ matrix.php }}
47-
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo
79+
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, pdo_mysql, pdo_pgsql, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo
4880
coverage: none
4981

5082
- name: Setup problem matchers
@@ -59,3 +91,10 @@ jobs:
5991
6092
- name: Execute tests
6193
run: vendor/bin/pest
94+
env:
95+
DB_DRIVER: ${{ matrix.db }}
96+
DB_HOST: 127.0.0.1
97+
DB_PORT: ${{ matrix.db == 'mysql' && '3306' || matrix.db == 'pgsql' && '5432' || '' }}
98+
DB_DATABASE: ${{ matrix.db != 'sqlite' && 'site_search_test' || '' }}
99+
DB_USERNAME: ${{ matrix.db == 'mysql' && 'root' || matrix.db == 'pgsql' && 'postgres' || '' }}
100+
DB_PASSWORD: ${{ matrix.db != 'sqlite' && 'password' || '' }}

UPGRADING.md

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,13 +172,48 @@ return new class extends Migration {
172172

173173
These columns are automatically populated after each crawl and shown in `site-search:list`.
174174

175+
#### 6. `SqliteDriver` replaced by `DatabaseDriver`
176+
177+
**Likelihood of impact:** 🔴 **HIGH** - Affects all users using the default driver
178+
179+
The `SqliteDriver` has been replaced by `DatabaseDriver`, which uses your application's database for full-text search. It supports SQLite, MySQL, and PostgreSQL.
180+
181+
If you were using the default `SqliteDriver`, update your config:
182+
183+
**Before:**
184+
```php
185+
'default_driver' => Spatie\SiteSearch\Drivers\SqliteDriver::class,
186+
```
187+
188+
**After:**
189+
```php
190+
'default_driver' => Spatie\SiteSearch\Drivers\DatabaseDriver::class,
191+
```
192+
193+
The new driver stores documents in a `site_search_documents` table instead of separate `.sqlite` files. Publish and run the new migration:
194+
195+
```bash
196+
php artisan vendor:publish --tag="site-search-migrations"
197+
php artisan migrate
198+
```
199+
200+
Then re-index your sites:
201+
202+
```bash
203+
php artisan site-search:crawl
204+
```
205+
206+
After re-indexing, you can safely delete the old `storage/site-search` directory.
207+
208+
If you were using a custom `database.connection` in the `extra` config, the key has changed from `sqlite.storage_path` to `database.connection`.
209+
175210
### New Features
176211

177212
After upgrading, you can:
178213

179-
1. **Use the SQLite driver** (now the default). No external dependencies required.
214+
1. **Use the database driver** (now the default). Supports SQLite, MySQL, and PostgreSQL with no external dependencies.
180215
```php
181-
'default_driver' => Spatie\SiteSearch\Drivers\SqliteDriver::class,
216+
'default_driver' => Spatie\SiteSearch\Drivers\DatabaseDriver::class,
182217
```
183218

184219
2. **Deep linking**. Search results now include anchor links to specific sections. Use `$hit->urlWithAnchor()` to get URLs like `https://example.com/page#section-id`. Requires re-indexing.

config/site-search.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,11 @@
6565
* to a search index.
6666
*
6767
* Available drivers:
68+
* - DatabaseDriver: uses your application's database with full-text search (SQLite FTS5, MySQL FULLTEXT, PostgreSQL tsvector)
6869
* - MeiliSearchDriver: uses Meilisearch as the search engine (requires a running Meilisearch instance)
69-
* - SqliteDriver: uses a local SQLite database with FTS5 full-text search (no external dependencies)
7070
* - ArrayDriver: in-memory driver for testing
7171
*/
72-
'default_driver' => Spatie\SiteSearch\Drivers\SqliteDriver::class,
72+
'default_driver' => Spatie\SiteSearch\Drivers\DatabaseDriver::class,
7373

7474
/*
7575
* This job is responsible for crawling your site. To customize this job,
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration {
8+
public function up(): void
9+
{
10+
Schema::create('site_search_documents', function (Blueprint $table) {
11+
$table->id();
12+
$table->string('index_name')->index();
13+
$table->string('document_id');
14+
$table->text('url');
15+
$table->text('anchor')->nullable();
16+
$table->text('page_title')->nullable();
17+
$table->text('h1')->nullable();
18+
$table->text('entry')->nullable();
19+
$table->text('description')->nullable();
20+
$table->integer('date_modified_timestamp')->nullable();
21+
$table->json('extra')->nullable();
22+
$table->timestamps();
23+
24+
$table->unique(['index_name', 'document_id']);
25+
});
26+
}
27+
};
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
---
2+
title: Using the database driver
3+
weight: 5
4+
---
5+
6+
The database driver is the default driver. It stores search documents in your application's database and uses the database's native full-text search capabilities. SQLite (FTS5), MySQL (FULLTEXT), and PostgreSQL (tsvector) are all supported.
7+
8+
## How it works
9+
10+
The database driver stores all indexed documents in a single `site_search_documents` table. Each document is associated with an `index_name`, which allows multiple search indexes to coexist in the same table.
11+
12+
Full-text search infrastructure (virtual tables, indexes, triggers) is created automatically at runtime based on which database you are using. The migration itself is database-agnostic.
13+
14+
### Database-specific behavior
15+
16+
**SQLite** uses FTS5 virtual tables with porter stemming and unicode support. BM25 ranking weights matches in headings higher than body content. Highlighted snippets are generated natively by FTS5.
17+
18+
**MySQL** uses FULLTEXT indexes with boolean mode search. Highlighting is done in PHP after the query.
19+
20+
**PostgreSQL** uses tsvector columns with GIN indexes and weighted vectors. `ts_rank()` is used for ranking and `ts_headline()` for highlighting.
21+
22+
### Search features
23+
24+
All three databases provide:
25+
26+
- Full-text search with stemming (e.g. "running" matches "run")
27+
- Prefix matching (e.g. "auth" matches "authentication")
28+
- Relevance ranking with field-specific weights
29+
- Highlighted snippets with matching terms wrapped in `<em>` tags
30+
- Deep linking with anchor links to specific sections (see [Retrieving results](/docs/laravel-site-search/v1/basic-usage/retrieving-results#deep-linking-to-sections))
31+
32+
## Using a different database connection
33+
34+
By default, the database driver uses your application's default database connection. You can use a different connection by setting a `database.connection` value in the `extra` attribute of the `site_search_configs` table:
35+
36+
```json
37+
{"database": {"connection": "mysql"}}
38+
```
39+
40+
This lets you store search data in a separate database from your application data.
41+
42+
## Differences from the Meilisearch driver
43+
44+
- No external service required, uses your existing database
45+
- No support for synonyms or custom ranking rules
46+
- Indexing is synchronous (no background processing)

docs/advanced-usage/using-the-sqlite-driver.md

Lines changed: 0 additions & 40 deletions
This file was deleted.

docs/basic-usage/high-level-overview.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ weight: 1
55

66
This package will crawl your entire site and will put the content in a search index. This way, the entire content of your site is searchable. Think of it as a private Google search index.
77

8-
The package supports two search drivers: SQLite (default) and Meilisearch. The search and indexing API is the same regardless of which driver you use.
8+
The package supports two search drivers: Database (default, supporting SQLite, MySQL, and PostgreSQL) and Meilisearch. The search and indexing API is the same regardless of which driver you use.
99

1010
The configuration for each site that needs to be crawled is saved in the `site_search_configs` table. You can manually create a row in that table or run this artisan command: [`site-search:create-index`](https://spatie.be/docs/laravel-site-search/v1/basic-usage/indexing-your-first-site).
1111

docs/installation-setup.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,11 @@ return [
118118
* to a search index.
119119
*
120120
* Available drivers:
121+
* - DatabaseDriver: uses your application's database with full-text search (SQLite FTS5, MySQL FULLTEXT, PostgreSQL tsvector)
121122
* - MeiliSearchDriver: uses Meilisearch as the search engine (requires a running Meilisearch instance)
122-
* - SqliteDriver: uses a local SQLite database with FTS5 full-text search (no external dependencies)
123123
* - ArrayDriver: in-memory driver for testing
124124
*/
125-
'default_driver' => Spatie\SiteSearch\Drivers\SqliteDriver::class,
125+
'default_driver' => Spatie\SiteSearch\Drivers\DatabaseDriver::class,
126126

127127
/*
128128
* This job is responsible for crawling your site. To customize this job,
@@ -135,6 +135,6 @@ return [
135135

136136
## Search driver
137137

138-
The default driver is SQLite, which uses SQLite FTS5 for full-text search. It requires no external services. The SQLite databases will be stored in `storage/site-search` by default. See [Using the SQLite driver](/docs/laravel-site-search/v1/advanced-usage/using-the-sqlite-driver) for more configuration options.
138+
The default driver is the database driver, which uses your application's database for full-text search. It supports SQLite (FTS5), MySQL (FULLTEXT), and PostgreSQL (tsvector) with no external services required. See [Using the database driver](/docs/laravel-site-search/v1/advanced-usage/using-the-database-driver) for more configuration options.
139139

140140
If you need advanced features like synonyms and custom ranking rules, you can [use the Meilisearch driver](/docs/laravel-site-search/v1/advanced-usage/using-the-meilisearch-driver) instead.

docs/introduction.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ This package can crawl and index one or more sites. You can think of it as a pri
77

88
Two search drivers are available:
99

10-
- SQLite (default): uses SQLite FTS5 for full-text search with no external dependencies. A great choice for most use cases.
10+
- Database (default): uses your application's database for full-text search. Supports SQLite (FTS5), MySQL (FULLTEXT), and PostgreSQL (tsvector). No external dependencies required.
1111
- Meilisearch: blazing fast search speeds, supports [synonyms](/docs/laravel-site-search/v1/advanced-usage/using-the-meilisearch-driver#customizing-index-settings) and other advanced Meilisearch features. Requires a running Meilisearch instance.
1212

1313
When crawling your site, multiple concurrent connections are used to speed up the crawling process.

docs/requirements.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ weight: 3
55

66
Laravel Site Search requires PHP 8.4+ and Laravel 12+.
77

8-
The default SQLite driver has no additional dependencies. When using the Meilisearch driver, a running Meilisearch instance is also required.
8+
The default database driver supports SQLite, MySQL, and PostgreSQL with no additional dependencies. When using the Meilisearch driver, a running Meilisearch instance is also required.
99

0 commit comments

Comments
 (0)