mirror of
https://github.com/BookStackApp/BookStack.git
synced 2026-07-24 05:34:36 +03:00
Added a formal object type to carry across vector search results. Added permission application and entity combining with vector search results. Also updated namespace from vectors to queries.
55 lines
1.7 KiB
PHP
55 lines
1.7 KiB
PHP
<?php
|
|
|
|
namespace BookStack\Search\Queries;
|
|
|
|
use BookStack\Entities\Tools\MixedEntityListLoader;
|
|
use BookStack\Permissions\PermissionApplicator;
|
|
use Exception;
|
|
|
|
class VectorSearchRunner
|
|
{
|
|
public function __construct(
|
|
protected VectorQueryServiceProvider $vectorQueryServiceProvider,
|
|
protected PermissionApplicator $permissions,
|
|
protected MixedEntityListLoader $entityLoader,
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* Run a vector search query to find results across entities.
|
|
* @return VectorSearchResult[]
|
|
* @throws Exception
|
|
*/
|
|
public function run(string $query): array
|
|
{
|
|
$queryService = $this->vectorQueryServiceProvider->get();
|
|
$queryVector = $queryService->generateEmbeddings($query);
|
|
|
|
// TODO - Test permissions applied
|
|
$topMatchesQuery = SearchVector::query()->select('text', 'entity_type', 'entity_id')
|
|
->selectRaw('VEC_DISTANCE_COSINE(VEC_FROMTEXT("[' . implode(',', $queryVector) . ']"), embedding) as distance')
|
|
->orderBy('distance', 'asc')
|
|
->having('distance', '<', 0.6)
|
|
->limit(10);
|
|
|
|
$query = $this->permissions->restrictEntityRelationQuery($topMatchesQuery, 'search_vectors', 'entity_id', 'entity_type');
|
|
$topMatches = $query->get();
|
|
|
|
$this->entityLoader->loadIntoRelations($topMatches->all(), 'entity', true);
|
|
|
|
$results = [];
|
|
|
|
foreach ($topMatches as $match) {
|
|
if ($match->relationLoaded('entity')) {
|
|
$results[] = new VectorSearchResult(
|
|
$match->getRelation('entity'),
|
|
$match->getAttribute('distance'),
|
|
$match->getAttribute('text'),
|
|
);
|
|
}
|
|
}
|
|
|
|
return $results;
|
|
}
|
|
}
|