mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-11-23 11:22:33 +01:00
Further search system refactorings
- Moved search term querying to its own method. - Updated Large content seeder to be more performant
This commit is contained in:
parent
e1b8fe45b0
commit
9e0164f4f4
@ -46,7 +46,7 @@ class SearchIndex
|
|||||||
*
|
*
|
||||||
* @param Entity[] $entities
|
* @param Entity[] $entities
|
||||||
*/
|
*/
|
||||||
protected function indexEntities(array $entities)
|
public function indexEntities(array $entities)
|
||||||
{
|
{
|
||||||
$terms = [];
|
$terms = [];
|
||||||
foreach ($entities as $entity) {
|
foreach ($entities as $entity) {
|
||||||
|
@ -133,29 +133,14 @@ class SearchRunner
|
|||||||
protected function buildQuery(SearchOptions $searchOpts, string $entityType = 'page', string $action = 'view'): EloquentBuilder
|
protected function buildQuery(SearchOptions $searchOpts, string $entityType = 'page', string $action = 'view'): EloquentBuilder
|
||||||
{
|
{
|
||||||
$entity = $this->entityProvider->get($entityType);
|
$entity = $this->entityProvider->get($entityType);
|
||||||
$entitySelect = $entity->newQuery();
|
$entityQuery = $entity->newQuery();
|
||||||
|
|
||||||
// Handle normal search terms
|
// Handle normal search terms
|
||||||
if (count($searchOpts->searches) > 0) {
|
$this->applyTermSearch($entityQuery, $searchOpts->searches, $entity);
|
||||||
$rawScoreSum = DB::raw('SUM(score) as score');
|
|
||||||
$subQuery = DB::table('search_terms')->select('entity_id', 'entity_type', $rawScoreSum);
|
|
||||||
$subQuery->where('entity_type', '=', $entity->getMorphClass());
|
|
||||||
$subQuery->where(function (Builder $query) use ($searchOpts) {
|
|
||||||
foreach ($searchOpts->searches as $inputTerm) {
|
|
||||||
$query->orWhere('term', 'like', $inputTerm . '%');
|
|
||||||
}
|
|
||||||
})->groupBy('entity_type', 'entity_id');
|
|
||||||
$entitySelect->join(DB::raw('(' . $subQuery->toSql() . ') as s'), function (JoinClause $join) {
|
|
||||||
$join->on('id', '=', 'entity_id');
|
|
||||||
})->addSelect($entity->getTable() . '.*')
|
|
||||||
->selectRaw('s.score')
|
|
||||||
->orderBy('score', 'desc');
|
|
||||||
$entitySelect->mergeBindings($subQuery);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle exact term matching
|
// Handle exact term matching
|
||||||
foreach ($searchOpts->exacts as $inputTerm) {
|
foreach ($searchOpts->exacts as $inputTerm) {
|
||||||
$entitySelect->where(function (EloquentBuilder $query) use ($inputTerm, $entity) {
|
$entityQuery->where(function (EloquentBuilder $query) use ($inputTerm, $entity) {
|
||||||
$query->where('name', 'like', '%' . $inputTerm . '%')
|
$query->where('name', 'like', '%' . $inputTerm . '%')
|
||||||
->orWhere($entity->textField, 'like', '%' . $inputTerm . '%');
|
->orWhere($entity->textField, 'like', '%' . $inputTerm . '%');
|
||||||
});
|
});
|
||||||
@ -163,18 +148,47 @@ class SearchRunner
|
|||||||
|
|
||||||
// Handle tag searches
|
// Handle tag searches
|
||||||
foreach ($searchOpts->tags as $inputTerm) {
|
foreach ($searchOpts->tags as $inputTerm) {
|
||||||
$this->applyTagSearch($entitySelect, $inputTerm);
|
$this->applyTagSearch($entityQuery, $inputTerm);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle filters
|
// Handle filters
|
||||||
foreach ($searchOpts->filters as $filterTerm => $filterValue) {
|
foreach ($searchOpts->filters as $filterTerm => $filterValue) {
|
||||||
$functionName = Str::camel('filter_' . $filterTerm);
|
$functionName = Str::camel('filter_' . $filterTerm);
|
||||||
if (method_exists($this, $functionName)) {
|
if (method_exists($this, $functionName)) {
|
||||||
$this->$functionName($entitySelect, $entity, $filterValue);
|
$this->$functionName($entityQuery, $entity, $filterValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->permissionService->enforceEntityRestrictions($entity, $entitySelect, $action);
|
return $this->permissionService->enforceEntityRestrictions($entity, $entityQuery, $action);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For the given search query, apply the queries for handling the regular search terms.
|
||||||
|
*/
|
||||||
|
protected function applyTermSearch(EloquentBuilder $entityQuery, array $terms, Entity $entity): void
|
||||||
|
{
|
||||||
|
if (count($terms) === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$subQuery = DB::table('search_terms')->select([
|
||||||
|
'entity_id',
|
||||||
|
'entity_type',
|
||||||
|
DB::raw('SUM(score) as score'),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$subQuery->where('entity_type', '=', $entity->getMorphClass());
|
||||||
|
$subQuery->where(function (Builder $query) use ($terms) {
|
||||||
|
foreach ($terms as $inputTerm) {
|
||||||
|
$query->orWhere('term', 'like', $inputTerm . '%');
|
||||||
|
}
|
||||||
|
})->groupBy('entity_type', 'entity_id');
|
||||||
|
$entityQuery->join(DB::raw('(' . $subQuery->toSql() . ') as s'), function (JoinClause $join) {
|
||||||
|
$join->on('id', '=', 'entity_id');
|
||||||
|
})->addSelect($entity->getTable() . '.*')
|
||||||
|
->selectRaw('s.score')
|
||||||
|
->orderBy('score', 'desc');
|
||||||
|
$entityQuery->mergeBindings($subQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,8 +33,9 @@ class LargeContentSeeder extends Seeder
|
|||||||
|
|
||||||
$largeBook->pages()->saveMany($pages);
|
$largeBook->pages()->saveMany($pages);
|
||||||
$largeBook->chapters()->saveMany($chapters);
|
$largeBook->chapters()->saveMany($chapters);
|
||||||
|
$all = array_merge([$largeBook], array_values($pages->all()), array_values($chapters->all()));
|
||||||
|
|
||||||
app()->make(PermissionService::class)->buildJointPermissions();
|
app()->make(PermissionService::class)->buildJointPermissionsForEntity($largeBook);
|
||||||
app()->make(SearchIndex::class)->indexAllEntities();
|
app()->make(SearchIndex::class)->indexEntities($all);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user