Skip to content

Commit 509af24

Browse files
committed
Search Index: Fixed SQL error when indexing large pages
Due to hitting statement placeholder limits (typically 65k) when inserting index terms for single page. Added test to cover. Also added skipped tests for tests we don't always want to run. For #5322
1 parent 5632fef commit 509af24

File tree

3 files changed

+38
-6
lines changed

3 files changed

+38
-6
lines changed

app/Search/SearchIndex.php

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public function indexEntity(Entity $entity): void
3030
{
3131
$this->deleteEntityTerms($entity);
3232
$terms = $this->entityToTermDataArray($entity);
33-
SearchTerm::query()->insert($terms);
33+
$this->insertTerms($terms);
3434
}
3535

3636
/**
@@ -46,10 +46,7 @@ public function indexEntities(array $entities): void
4646
array_push($terms, ...$entityTerms);
4747
}
4848

49-
$chunkedTerms = array_chunk($terms, 500);
50-
foreach ($chunkedTerms as $termChunk) {
51-
SearchTerm::query()->insert($termChunk);
52-
}
49+
$this->insertTerms($terms);
5350
}
5451

5552
/**
@@ -99,6 +96,19 @@ public function deleteEntityTerms(Entity $entity): void
9996
$entity->searchTerms()->delete();
10097
}
10198

99+
/**
100+
* Insert the given terms into the database.
101+
* Chunks through the given terms to remain within database limits.
102+
* @param array[] $terms
103+
*/
104+
protected function insertTerms(array $terms): void
105+
{
106+
$chunkedTerms = array_chunk($terms, 500);
107+
foreach ($chunkedTerms as $termChunk) {
108+
SearchTerm::query()->insert($termChunk);
109+
}
110+
}
111+
102112
/**
103113
* Create a scored term array from the given text, where the keys are the terms
104114
* and the values are their scores.

tests/Entity/EntitySearchTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use BookStack\Entities\Models\Book;
77
use BookStack\Entities\Models\Bookshelf;
88
use BookStack\Entities\Models\Chapter;
9+
use Illuminate\Support\Str;
910
use Tests\TestCase;
1011

1112
class EntitySearchTest extends TestCase
@@ -477,6 +478,25 @@ public function test_terms_in_headers_have_an_adjusted_index_score()
477478
$this->assertEquals(2, $scoreByTerm->get('TermG'));
478479
}
479480

481+
public function test_indexing_works_as_expected_for_page_with_lots_of_terms()
482+
{
483+
$this->markTestSkipped('Time consuming test');
484+
485+
$count = 100000;
486+
$text = '';
487+
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_#';
488+
for ($i = 0; $i < $count; $i++) {
489+
$text .= substr(str_shuffle($chars), 0, 5) . ' ';
490+
}
491+
492+
$page = $this->entities->newPage(['name' => 'Test page A', 'html' => '<p>' . $text . '</p>']);
493+
494+
$termCount = $page->searchTerms()->count();
495+
496+
// Expect at least 90% unique rate
497+
$this->assertGreaterThan($count * 0.9, $termCount);
498+
}
499+
480500
public function test_name_and_content_terms_are_merged_to_single_score()
481501
{
482502
$page = $this->entities->newPage(['name' => 'TermA', 'html' => '

tests/LanguageTest.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@ public function test_locales_list_set_properly()
2727
}
2828

2929
// Not part of standard phpunit test runs since we sometimes expect non-added langs.
30-
public function do_test_locales_all_have_language_dropdown_entry()
30+
public function test_locales_all_have_language_dropdown_entry()
3131
{
32+
$this->markTestSkipped('Only used when checking language inclusion');
33+
3234
$dropdownLocales = array_keys(trans('settings.language_select', [], 'en'));
3335
sort($dropdownLocales);
3436
sort($this->langs);

0 commit comments

Comments
 (0)