]> BookStack Code Mirror - bookstack/commitdiff
Further search system refactorings
authorDan Brown <redacted>
Mon, 8 Nov 2021 11:29:25 +0000 (11:29 +0000)
committerDan Brown <redacted>
Mon, 8 Nov 2021 11:29:25 +0000 (11:29 +0000)
- Moved search term querying to its own method.
- Updated Large content seeder to be more performant

app/Entities/Tools/SearchIndex.php
app/Entities/Tools/SearchRunner.php
database/seeders/LargeContentSeeder.php

index cc0b32d6a00f1437ce2845b3f1e107aae663f39f..541f0699442300fdf6de82248f5862fdadbaab9c 100644 (file)
@@ -46,7 +46,7 @@ class SearchIndex
      *
      * @param Entity[] $entities
      */
-    protected function indexEntities(array $entities)
+    public function indexEntities(array $entities)
     {
         $terms = [];
         foreach ($entities as $entity) {
index dc54649be8ffb56156636a111bd201f06ba83503..6296c70e71d4b2b05ef329ebbadcd2827a110963 100644 (file)
@@ -133,29 +133,14 @@ class SearchRunner
     protected function buildQuery(SearchOptions $searchOpts, string $entityType = 'page', string $action = 'view'): EloquentBuilder
     {
         $entity = $this->entityProvider->get($entityType);
-        $entitySelect = $entity->newQuery();
+        $entityQuery = $entity->newQuery();
 
         // Handle normal search terms
-        if (count($searchOpts->searches) > 0) {
-            $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);
-        }
+        $this->applyTermSearch($entityQuery, $searchOpts->searches, $entity);
 
         // Handle exact term matching
         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 . '%')
                     ->orWhere($entity->textField, 'like', '%' . $inputTerm . '%');
             });
@@ -163,18 +148,47 @@ class SearchRunner
 
         // Handle tag searches
         foreach ($searchOpts->tags as $inputTerm) {
-            $this->applyTagSearch($entitySelect, $inputTerm);
+            $this->applyTagSearch($entityQuery, $inputTerm);
         }
 
         // Handle filters
         foreach ($searchOpts->filters as $filterTerm => $filterValue) {
             $functionName = Str::camel('filter_' . $filterTerm);
             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);
     }
 
     /**
index e8b6d74f6a4e9f8de2cc70d6ea6ee6b3f5c663be..dd916597876ba507fecd10c40739e37ff01a1672 100644 (file)
@@ -33,8 +33,9 @@ class LargeContentSeeder extends Seeder
 
         $largeBook->pages()->saveMany($pages);
         $largeBook->chapters()->saveMany($chapters);
+        $all = array_merge([$largeBook], array_values($pages->all()), array_values($chapters->all()));
 
-        app()->make(PermissionService::class)->buildJointPermissions();
-        app()->make(SearchIndex::class)->indexAllEntities();
+        app()->make(PermissionService::class)->buildJointPermissionsForEntity($largeBook);
+        app()->make(SearchIndex::class)->indexEntities($all);
     }
 }