ajuste na pesquisa de informacao, para passar a dar prioridade
This commit is contained in:
@@ -29,8 +29,7 @@ class GlobalSearchController extends Controller
|
||||
if ($tokens !== []) {
|
||||
$factories = [
|
||||
'Páginas e serviços' => function () use ($search, $tokens, $term) {
|
||||
$pages = array_values(array_filter($this->pages(), fn ($page) => $search->matches(implode(' ', $page), $tokens)
|
||||
&& $search->score($page['title'], $term, $tokens) > 0));
|
||||
$pages = array_values(array_filter($this->pages(), fn ($page) => $search->matches(implode(' ', $page), $tokens)));
|
||||
usort($pages, fn ($a, $b) => $search->score($b['title'], $term, $tokens) <=> $search->score($a['title'], $term, $tokens)
|
||||
?: strcmp($a['title'], $b['title']) ?: strcmp($a['url'], $b['url']));
|
||||
|
||||
|
||||
@@ -82,10 +82,10 @@ final class SearchTerms
|
||||
{
|
||||
$title = mb_strtolower(Str::ascii($title));
|
||||
$phrase = mb_strtolower(Str::ascii(trim($phrase)));
|
||||
$score = $title === $phrase ? 1000 : (str_contains($title, $phrase) ? 400 : 0);
|
||||
$score = $title === $phrase ? 1000 : (str_starts_with($title, $phrase) ? 600 : (str_contains($title, $phrase) ? 400 : 0));
|
||||
foreach ($tokens as $token) {
|
||||
if ($this->matches($title, [$token])) {
|
||||
$score += 20;
|
||||
$score++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,15 +97,15 @@ final class SearchTerms
|
||||
{
|
||||
$column = $this->normalizedColumn($titleColumn);
|
||||
$phrase = mb_strtolower(Str::ascii(trim($phrase)));
|
||||
$sql = "CASE WHEN {$column} = ? THEN 1000 WHEN {$column} LIKE ? ESCAPE '!' THEN 400 ELSE 0 END";
|
||||
$bindings = [$phrase, $this->pattern($phrase)];
|
||||
$sql = "CASE WHEN {$column} = ? THEN 1000 WHEN {$column} LIKE ? ESCAPE '!' THEN 600 WHEN {$column} LIKE ? ESCAPE '!' THEN 400 ELSE 0 END";
|
||||
$bindings = [$phrase, ltrim($this->pattern($phrase), '%'), $this->pattern($phrase)];
|
||||
foreach ($tokens as $token) {
|
||||
$conditions = [];
|
||||
foreach ($this->variants($token) as $variant) {
|
||||
$conditions[] = "{$column} LIKE ? ESCAPE '!'";
|
||||
$bindings[] = $this->pattern($variant);
|
||||
}
|
||||
$sql .= ' + CASE WHEN ('.implode(' OR ', $conditions).') THEN 20 ELSE 0 END';
|
||||
$sql .= ' + CASE WHEN ('.implode(' OR ', $conditions).') THEN 1 ELSE 0 END';
|
||||
}
|
||||
$query->orderByRaw('('.$sql.') DESC', $bindings)->orderBy($titleColumn)->orderBy($tieColumn);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Tests\Unit;
|
||||
|
||||
use App\Services\FederatedSearch;
|
||||
use App\Services\SearchTerms;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class FederatedSearchTest extends TestCase
|
||||
@@ -44,4 +45,24 @@ final class FederatedSearchTest extends TestCase
|
||||
$result = (new FederatedSearch)->page($factories, 1, 5, fn ($item) => $item['score']);
|
||||
$this->assertSame(['Sectores', 'Informação'], array_column($result['data'], 'title'));
|
||||
}
|
||||
|
||||
public function test_direct_matches_precede_associations_across_sources_and_pages(): void
|
||||
{
|
||||
$search = new SearchTerms;
|
||||
$term = 'corredor da beira';
|
||||
$tokens = $search->tokens($term);
|
||||
$sources = [
|
||||
'Oportunidades' => fn () => ['count' => 2, 'fetch' => fn ($offset, $limit) => array_slice([
|
||||
['title' => 'Açúcar no Corredor da Beira'], ['title' => 'Produção de açúcar'],
|
||||
], $offset, $limit)],
|
||||
'Carteira' => fn () => ['count' => 1, 'fetch' => fn ($offset, $limit) => array_slice([
|
||||
['title' => 'Corredor da Beira'],
|
||||
], $offset, $limit)],
|
||||
];
|
||||
$score = fn ($item) => $search->score($item['title'], $term, $tokens);
|
||||
$service = new FederatedSearch;
|
||||
|
||||
$this->assertSame(['Corredor da Beira', 'Açúcar no Corredor da Beira'], array_column($service->page($sources, 1, 2, $score)['data'], 'title'));
|
||||
$this->assertSame(['Produção de açúcar'], array_column($service->page($sources, 2, 2, $score)['data'], 'title'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,4 +56,29 @@ final class SearchTermsTest extends TestCase
|
||||
$this->assertGreaterThan($search->score('Como investir', 'investir', ['investir']), $search->score('Investir', 'investir', ['investir']));
|
||||
$this->assertSame(['de'], $search->tokens('de'));
|
||||
}
|
||||
|
||||
public function test_direct_titles_precede_titles_and_descriptions_that_reference_the_query(): void
|
||||
{
|
||||
$search = new SearchTerms;
|
||||
$phrase = 'corredor da beira';
|
||||
$tokens = $search->tokens($phrase);
|
||||
$titles = ['Açúcar no Corredor da Beira', 'Corredor da Beira e investimentos', 'Corredor da Beira', 'Produção de açúcar'];
|
||||
usort($titles, fn ($a, $b) => $search->score($b, $phrase, $tokens) <=> $search->score($a, $phrase, $tokens));
|
||||
|
||||
$this->assertSame(['Corredor da Beira', 'Corredor da Beira e investimentos', 'Açúcar no Corredor da Beira', 'Produção de açúcar'], $titles);
|
||||
$this->assertSame($search->score('Corredor da Beira', $phrase, $tokens), $search->score('CORREDOR DA BEIRA', $phrase, $tokens));
|
||||
}
|
||||
|
||||
public function test_database_relevance_uses_the_same_levels_and_escaped_prefix(): void
|
||||
{
|
||||
$connection = new PostgresConnection(fn () => throw new \LogicException('A database must not be opened.'));
|
||||
$query = $connection->table('records');
|
||||
$search = new SearchTerms;
|
||||
$search->orderByRelevance($query, 'title', '100% açúcar', $search->tokens('100% açúcar'), 'id');
|
||||
|
||||
$this->assertStringContainsString('THEN 1000', $query->toSql());
|
||||
$this->assertStringContainsString('THEN 600', $query->toSql());
|
||||
$this->assertStringContainsString('THEN 400', $query->toSql());
|
||||
$this->assertSame(['100% acucar', '100!% acucar%', '%100!% acucar%'], array_slice($query->getBindings(), 0, 3));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user