mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-12 21:34:25 +00:00
adaptations for third party search
This commit is contained in:
parent
f4369553e1
commit
e9192c5011
@ -27,7 +27,7 @@ class SearchUserApiProvider implements SearchApiInterface
|
|||||||
->setSelectPertinence("GREATEST(SIMILARITY(LOWER(UNACCENT(?)), u.usernamecanonical),
|
->setSelectPertinence("GREATEST(SIMILARITY(LOWER(UNACCENT(?)), u.usernamecanonical),
|
||||||
SIMILARITY(LOWER(UNACCENT(?)), u.emailcanonical))", [ $pattern, $pattern ])
|
SIMILARITY(LOWER(UNACCENT(?)), u.emailcanonical))", [ $pattern, $pattern ])
|
||||||
->setFromClause("users AS u")
|
->setFromClause("users AS u")
|
||||||
->setWhereClause("SIMILARITY(LOWER(UNACCENT(?)), u.usernamecanonical) > 0.15
|
->setWhereClauses("SIMILARITY(LOWER(UNACCENT(?)), u.usernamecanonical) > 0.15
|
||||||
OR
|
OR
|
||||||
SIMILARITY(LOWER(UNACCENT(?)), u.emailcanonical) > 0.15
|
SIMILARITY(LOWER(UNACCENT(?)), u.emailcanonical) > 0.15
|
||||||
", [ $pattern, $pattern ]);
|
", [ $pattern, $pattern ]);
|
||||||
|
@ -12,8 +12,8 @@ class SearchApiQuery
|
|||||||
private array $pertinenceParams = [];
|
private array $pertinenceParams = [];
|
||||||
private ?string $fromClause = null;
|
private ?string $fromClause = null;
|
||||||
private array $fromClauseParams = [];
|
private array $fromClauseParams = [];
|
||||||
private ?string $whereClause = null;
|
private array $whereClauses = [];
|
||||||
private array $whereClauseParams = [];
|
private array $whereClausesParams = [];
|
||||||
|
|
||||||
public function setSelectKey(string $selectKey, array $params = []): self
|
public function setSelectKey(string $selectKey, array $params = []): self
|
||||||
{
|
{
|
||||||
@ -47,16 +47,39 @@ class SearchApiQuery
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setWhereClause(string $whereClause, array $params = []): self
|
/**
|
||||||
|
* Set the where clause and replace all existing ones.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function setWhereClauses(string $whereClause, array $params = []): self
|
||||||
{
|
{
|
||||||
$this->whereClause = $whereClause;
|
$this->whereClauses = [$whereClause];
|
||||||
$this->whereClauseParams = $params;
|
$this->whereClausesParams = [$params];
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a where clause.
|
||||||
|
*
|
||||||
|
* This will add to previous where clauses with and `AND` join
|
||||||
|
*
|
||||||
|
* @param string $whereClause
|
||||||
|
* @param array $params
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function andWhereClause(string $whereClause, array $params = []): self
|
||||||
|
{
|
||||||
|
$this->whereClauses[] = $whereClause;
|
||||||
|
$this->whereClausesParams[] = $params;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildQuery(): string
|
public function buildQuery(): string
|
||||||
{
|
{
|
||||||
|
$where = \implode(' AND ', $this->whereClauses);
|
||||||
|
|
||||||
return \strtr("SELECT
|
return \strtr("SELECT
|
||||||
'{key}' AS key,
|
'{key}' AS key,
|
||||||
{metadata} AS metadata,
|
{metadata} AS metadata,
|
||||||
@ -68,7 +91,7 @@ class SearchApiQuery
|
|||||||
'{metadata}' => $this->jsonbMetadata,
|
'{metadata}' => $this->jsonbMetadata,
|
||||||
'{pertinence}' => $this->pertinence,
|
'{pertinence}' => $this->pertinence,
|
||||||
'{from}' => $this->fromClause,
|
'{from}' => $this->fromClause,
|
||||||
'{where}' => $this->whereClause,
|
'{where}' => $where,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +102,7 @@ class SearchApiQuery
|
|||||||
$this->jsonbMetadataParams,
|
$this->jsonbMetadataParams,
|
||||||
$this->pertinenceParams,
|
$this->pertinenceParams,
|
||||||
$this->fromClauseParams,
|
$this->fromClauseParams,
|
||||||
$this->whereClauseParams,
|
\array_merge([], ...$this->whereClausesParams),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Search;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Search\SearchApiQuery;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class SearchApiQueryTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testMultipleWhereClauses()
|
||||||
|
{
|
||||||
|
$q = new SearchApiQuery();
|
||||||
|
$q->setSelectJsonbMetadata('boum')
|
||||||
|
->setSelectKey('bim')
|
||||||
|
->setSelectPertinence('1')
|
||||||
|
->setFromClause('badaboum')
|
||||||
|
->andWhereClause('foo', [ 'alpha' ])
|
||||||
|
->andWhereClause('bar', [ 'beta' ])
|
||||||
|
;
|
||||||
|
|
||||||
|
$query = $q->buildQuery();
|
||||||
|
|
||||||
|
$this->assertStringContainsString('foo AND bar', $query);
|
||||||
|
$this->assertEquals(['alpha', 'beta'], $q->buildParameters());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testWithoutWhereClause()
|
||||||
|
{
|
||||||
|
$q = new SearchApiQuery();
|
||||||
|
$q->setSelectJsonbMetadata('boum')
|
||||||
|
->setSelectKey('bim')
|
||||||
|
->setSelectPertinence('1')
|
||||||
|
->setFromClause('badaboum')
|
||||||
|
;
|
||||||
|
|
||||||
|
$this->assertTrue(\is_string($q->buildQuery()));
|
||||||
|
$this->assertEquals([], $q->buildParameters());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -26,7 +26,7 @@ class SearchPersonApiProvider implements SearchApiInterface
|
|||||||
"(person.fullnamecanonical LIKE '%' || LOWER(UNACCENT(?)) || '%')::int".
|
"(person.fullnamecanonical LIKE '%' || LOWER(UNACCENT(?)) || '%')::int".
|
||||||
")", [ $pattern, $pattern ])
|
")", [ $pattern, $pattern ])
|
||||||
->setFromClause("chill_person_person AS person")
|
->setFromClause("chill_person_person AS person")
|
||||||
->setWhereClause("LOWER(UNACCENT(?)) <<% person.fullnamecanonical OR ".
|
->setWhereClauses("LOWER(UNACCENT(?)) <<% person.fullnamecanonical OR ".
|
||||||
"person.fullnamecanonical LIKE '%' || LOWER(UNACCENT(?)) || '%' ", [ $pattern, $pattern ])
|
"person.fullnamecanonical LIKE '%' || LOWER(UNACCENT(?)) || '%' ", [ $pattern, $pattern ])
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -5,7 +5,36 @@ namespace Chill\ThirdPartyBundle\Search;
|
|||||||
use Chill\MainBundle\Search\SearchApiInterface;
|
use Chill\MainBundle\Search\SearchApiInterface;
|
||||||
use Chill\MainBundle\Search\SearchApiQuery;
|
use Chill\MainBundle\Search\SearchApiQuery;
|
||||||
use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository;
|
use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository;
|
||||||
|
use function explode;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal note: test query for parametrizing / testing:
|
||||||
|
*
|
||||||
|
WITH rows AS (
|
||||||
|
SELECT 'aide a domicile en milieu rural admr' AS c, 'la roche sur yon' AS l
|
||||||
|
UNION
|
||||||
|
SELECT 'aide a domicile en milieu rural admr' AS c, 'fontenay-le-comte' AS l
|
||||||
|
), searches AS (
|
||||||
|
SELECT 'admr roche' AS s, 'admr' AS s1, 'roche' As s2
|
||||||
|
UNION
|
||||||
|
SELECT 'admr font' AS s, 'admr' AS s1, 'font' AS s2
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
c, l, s, s1, s2,
|
||||||
|
strict_word_similarity(s, c)
|
||||||
|
+ (c LIKE '%' || s1 || '%')::int
|
||||||
|
+ (c LIKE '%' || s2 || '%')::int
|
||||||
|
+ (l LIKE '%' || s1 || '%')::int
|
||||||
|
+ (l LIKE '%' || s2 || '%')::int,
|
||||||
|
l LIKE '%' || s1 || '%',
|
||||||
|
l LIKE '%' || s2 || '%'
|
||||||
|
FROM rows, searches
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate query for searching amongst third parties
|
||||||
|
*/
|
||||||
class ThirdPartyApiSearch implements SearchApiInterface
|
class ThirdPartyApiSearch implements SearchApiInterface
|
||||||
{
|
{
|
||||||
private ThirdPartyRepository $thirdPartyRepository;
|
private ThirdPartyRepository $thirdPartyRepository;
|
||||||
@ -17,18 +46,45 @@ class ThirdPartyApiSearch implements SearchApiInterface
|
|||||||
|
|
||||||
public function provideQuery(string $pattern, array $parameters): SearchApiQuery
|
public function provideQuery(string $pattern, array $parameters): SearchApiQuery
|
||||||
{
|
{
|
||||||
return (new SearchApiQuery)
|
$query = (new SearchApiQuery)
|
||||||
->setSelectKey('tparty')
|
->setSelectKey('tparty')
|
||||||
->setSelectJsonbMetadata("jsonb_build_object('id', tparty.id)")
|
->setSelectJsonbMetadata("jsonb_build_object('id', tparty.id)")
|
||||||
->setSelectPertinence("GREATEST(".
|
->setFromClause('chill_3party.third_party AS tparty
|
||||||
"STRICT_WORD_SIMILARITY(LOWER(UNACCENT(?)), tparty.canonicalized),".
|
LEFT JOIN chill_main_address cma ON cma.id = tparty.address_id
|
||||||
"(tparty.canonicalized LIKE '%' || LOWER(UNACCENT(?)) || '%')::int".
|
LEFT JOIN chill_main_postal_code cmpc ON cma.postcode_id = cmpc.id
|
||||||
")", [ $pattern, $pattern ])
|
LEFT JOIN chill_3party.third_party AS parent ON tparty.parent_id = parent.id
|
||||||
->setFromClause('chill_3party.third_party AS tparty')
|
LEFT JOIN chill_main_address cma_p ON parent.address_id = cma_p.id
|
||||||
->setWhereClause("tparty.active IS TRUE ".
|
LEFT JOIN chill_main_postal_code cmpc_p ON cma_p.postcode_id = cmpc.id')
|
||||||
"AND (LOWER(UNACCENT(?)) <<% tparty.canonicalized OR ".
|
->andWhereClause("tparty.active IS TRUE")
|
||||||
"tparty.canonicalized LIKE '%' || LOWER(UNACCENT(?)) || '%')", [ $pattern, $pattern ])
|
;
|
||||||
;
|
|
||||||
|
$strs = explode(' ', $pattern);
|
||||||
|
$wheres = [];
|
||||||
|
$whereArgs = [];
|
||||||
|
$pertinence = [];
|
||||||
|
$pertinenceArgs = [];
|
||||||
|
|
||||||
|
foreach ($strs as $str) {
|
||||||
|
if (!empty($str)) {
|
||||||
|
$wheres[] = "(LOWER(UNACCENT(?)) <<% tparty.canonicalized OR
|
||||||
|
tparty.canonicalized LIKE '%' || LOWER(UNACCENT(?)) || '%')";
|
||||||
|
$whereArgs[] = [$str, $str];
|
||||||
|
$pertinence[] = "STRICT_WORD_SIMILARITY(LOWER(UNACCENT(?)), tparty.canonicalized) + ".
|
||||||
|
"(tparty.canonicalized LIKE '%s' || LOWER(UNACCENT(?)) || '%')::int + ".
|
||||||
|
// take postcode label into account, but lower than the canonicalized field
|
||||||
|
"COALESCE((LOWER(UNACCENT(cmpc.label)) LIKE '%' || LOWER(UNACCENT(?)) || '%')::int * 0.3, 0) + ".
|
||||||
|
"COALESCE((LOWER(UNACCENT(cmpc_p.label)) LIKE '%' || LOWER(UNACCENT(?)) || '%')::int * 0.3, 0)";
|
||||||
|
$pertinenceArgs[] = [$str, $str, $str, $str];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$query
|
||||||
|
->setSelectPertinence(\implode(' + ', $pertinence), \array_merge([],
|
||||||
|
...$pertinenceArgs))
|
||||||
|
->andWhereClause(\implode(' OR ', $wheres), \array_merge([],
|
||||||
|
...$whereArgs));
|
||||||
|
|
||||||
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function supportsTypes(string $pattern, array $types, array $parameters): bool
|
public function supportsTypes(string $pattern, array $types, array $parameters): bool
|
||||||
|
Loading…
x
Reference in New Issue
Block a user