orm query: supporting match
This commit is contained in:
@@ -107,6 +107,14 @@ abstract class Base
|
||||
'LENGTH'
|
||||
];
|
||||
|
||||
protected $matchFunctionList = ['MATCH_BOOLEAN', 'MATCH_NATURAL_LANGUAGE', 'MATCH_QUERY_EXPANSION'];
|
||||
|
||||
protected $matchFunctionMap = [
|
||||
'MATCH_BOOLEAN' => 'IN BOOLEAN MODE',
|
||||
'MATCH_NATURAL_LANGUAGE' => 'IN NATURAL LANGUAGE MODE',
|
||||
'MATCH_QUERY_EXPANSION' => 'WITH QUERY EXPANSION'
|
||||
];
|
||||
|
||||
protected $entityFactory;
|
||||
|
||||
protected $pdo;
|
||||
@@ -308,6 +316,43 @@ abstract class Base
|
||||
return $function . '(' . $part . ')';
|
||||
}
|
||||
|
||||
protected function convertMatchExpression($entity, $expression)
|
||||
{
|
||||
$delimiterPosition = strpos($expression, ':');
|
||||
if ($delimiterPosition === false) {
|
||||
throw new \Exception("Bad MATCH usage.");
|
||||
}
|
||||
|
||||
$function = substr($expression, 0, $delimiterPosition);
|
||||
$rest = substr($expression, $delimiterPosition + 1);
|
||||
|
||||
if (empty($rest)) {
|
||||
throw new \Exception("Empty MATCH parameters.");
|
||||
}
|
||||
|
||||
$delimiterPosition = strpos($rest, ':');
|
||||
if ($delimiterPosition === false) {
|
||||
throw new \Exception("Bad MATCH usage.");
|
||||
}
|
||||
|
||||
$columns = substr($rest, 0, $delimiterPosition);
|
||||
$query = substr($rest, $delimiterPosition + 1);
|
||||
|
||||
$columnList = explode(',', $columns);
|
||||
|
||||
foreach ($columnList as $i => $column) {
|
||||
$columnList[$i] = $this->sanitize($column);
|
||||
}
|
||||
|
||||
$query = $this->quote($query);
|
||||
|
||||
if (!in_array($function, $this->matchFunctionList)) return;
|
||||
$modePart = ' ' . $this->matchFunctionMap[$function];
|
||||
|
||||
$result = "MATCH (" . implode(',', $columnList) . ") AGAINST (" . $query . "" . $modePart . ")";
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function convertComplexExpression($entity, $field, $distinct = false)
|
||||
{
|
||||
@@ -317,7 +362,14 @@ abstract class Base
|
||||
$entityType = $entity->getEntityType();
|
||||
|
||||
if (strpos($field, ':')) {
|
||||
list($function, $field) = explode(':', $field);
|
||||
$dilimeterPosition = strpos($field, ':');
|
||||
$function = substr($field, 0, $dilimeterPosition);
|
||||
|
||||
if (in_array($function, $this->matchFunctionList)) {
|
||||
return $this->convertMatchExpression($entity, $field);
|
||||
}
|
||||
|
||||
$field = substr($field, $dilimeterPosition + 1);
|
||||
}
|
||||
if (!empty($function)) {
|
||||
$function = preg_replace('/[^A-Za-z0-9_]+/', '', $function);
|
||||
@@ -724,6 +776,13 @@ abstract class Base
|
||||
foreach ($whereClause as $field => $value) {
|
||||
|
||||
if (is_int($field)) {
|
||||
if (is_string($value)) {
|
||||
if (strpos($value, 'MATCH_') === 0) {
|
||||
$rightPart = $this->convertMatchExpression($entity, $value);
|
||||
$whereParts[] = $rightPart;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$field = 'AND';
|
||||
}
|
||||
|
||||
|
||||
@@ -442,4 +442,57 @@ class QueryTest extends \PHPUnit\Framework\TestCase
|
||||
"HAVING COUNT(comment.id) > '1'";
|
||||
$this->assertEquals($expectedSql, $sql);
|
||||
}
|
||||
|
||||
public function testMatch1()
|
||||
{
|
||||
$sql = $this->query->createSelectQuery('Article', array(
|
||||
'select' => ['id', 'name'],
|
||||
'whereClause' => [
|
||||
'MATCH_BOOLEAN:name,description:test +hello',
|
||||
'id!=' => null
|
||||
]
|
||||
));
|
||||
|
||||
$expectedSql =
|
||||
"SELECT article.id AS `id`, article.name AS `name` FROM `article` " .
|
||||
"WHERE MATCH (name,description) AGAINST ('test +hello' IN BOOLEAN MODE) AND article.id IS NOT NULL AND article.deleted = '0'";
|
||||
|
||||
$this->assertEquals($expectedSql, $sql);
|
||||
}
|
||||
|
||||
public function testMatch2()
|
||||
{
|
||||
$sql = $this->query->createSelectQuery('Article', array(
|
||||
'select' => ['id', 'name'],
|
||||
'whereClause' => [
|
||||
'MATCH_NATURAL_LANGUAGE:description:"test hello"'
|
||||
]
|
||||
));
|
||||
|
||||
$expectedSql =
|
||||
"SELECT article.id AS `id`, article.name AS `name` FROM `article` " .
|
||||
"WHERE MATCH (description) AGAINST ('\"test hello\"' IN NATURAL LANGUAGE MODE) AND article.deleted = '0'";
|
||||
|
||||
$this->assertEquals($expectedSql, $sql);
|
||||
}
|
||||
|
||||
public function testMatch3()
|
||||
{
|
||||
$sql = $this->query->createSelectQuery('Article', array(
|
||||
'select' => ['id', 'MATCH_BOOLEAN:description:test'],
|
||||
'whereClause' => [
|
||||
'MATCH_BOOLEAN:description:test'
|
||||
],
|
||||
'orderBy' => [
|
||||
[2, 'DESC']
|
||||
]
|
||||
));
|
||||
|
||||
$expectedSql =
|
||||
"SELECT article.id AS `id`, MATCH (description) AGAINST ('test' IN BOOLEAN MODE) AS `MATCH_BOOLEAN:description:test` FROM `article` " .
|
||||
"WHERE MATCH (description) AGAINST ('test' IN BOOLEAN MODE) AND article.deleted = '0' " .
|
||||
"ORDER BY 2 DESC";
|
||||
|
||||
$this->assertEquals($expectedSql, $sql);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,5 +242,3 @@ class Article extends TEntity
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user