如何将 QueryBuilder 与 andWhere 一起用于 json
How do I use QueryBuilder with andWhere for json
拜托,我只是 querybuilder 的新手,确切地说我不知道如何在 where 子句中使用 json 对象。非常感谢您的 swift 帮助。
"post_id": 1
"post": ""
"author": [{"id": 2, "email": "example@example.com"}, {"id": 3, "email": "example2@example.com"}]
"post_id": 2
"post": ""
"author": [{"id": 4, "email": "example@example.com"}, {"id": 9, "email": "example2@example.com"}]
我想查询作者->id 为current_user的tablePost。我已经尽力了。我已经安装了 composer require scienta/doctrine-json-functions
当我运行它的时候,我得到了
"An exception occurred while executing a query: SQLSTATE[42883]: Undefined function: 7 ERROR: operator does not exist: json = unknown\nLINE 1: ... w0_ WHERE json_extract_path(w0_.author, ) = ORDER...\n ^\nHINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.",
我没主意了。
private function addWhere(QueryBuilder $queryBuilder, string $resourceClass): void
{
if (WorkshopSession::class !== $resourceClass || $this->security->isGranted('ROLE_ADMIN') || null === $user = $this->security->getUser()) {
return;
}
$rootAlias = $queryBuilder->getRootAliases()[0];
$queryBuilder->andWhere("JSON_EXTRACT_PATH(o.author, :id) = :current_user");
$queryBuilder->setParameter('id', 'o.id');
$queryBuilder->setParameter('current_user', $user->getId());
}
我正在使用 api 平台并使用学说扩展。数据库服务器 - postgreSQL
您需要做的第一件事是将选项切换到 jsonb,这将帮助您轻松遍历 json 树,而无需将自己置于框内。
select * from post where author @> '[{"id": "2"}]';
运行 这在您的传统 sql 中应该有效,然后将其转换为 DQL。这可能很棘手,因为 DQL 中没有“@>”,但您可以利用自定义 DQL 用户定义函数。我建议这样做而不是安装第三方库,因为第三方库会增加抽象层和版本控制问题(弃用)的复杂性。
正如您在下面看到的,我们使用了 FunctionNode、SqlWalker、Lexer 和 Parser。
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\SqlWalker;
use Doctrine\ORM\Query\AST\Node;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\Lexer;
use function sprintf;
class JsonContains extends FunctionNode
{
/** @var Node */
/** @psalm-suppress all */
private $expr1;
/** @var Node */
/** @psalm-suppress all */
private $expr2;
public function parse(Parser $parser) : void
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->expr1 = $parser->StringPrimary();
$parser->match(Lexer::T_COMMA);
$this->expr2 = $parser->StringPrimary();
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
public function getSql(SqlWalker $sqlWalker) : string
{
return sprintf(
'(%s @> %s)',
$this->expr1->dispatch($sqlWalker),
$this->expr2->dispatch($sqlWalker)
);
}
}
一旦你定义了这个,你就可以注册它。 Symfony 5 以上建议使用 doctrine.yaml。您可以通过以下方式注册
dql:
string_functions:
JSON_CONTAINS: App\Doctrine\Extension\Functions\DQL\UDF\JsonContains
然后在你的扩展中,你可以简单地使用它。
$queryBuilder->andWhere("JSON_CONTAINS(".$rootAlias .".author, :current_user) = true");
$queryBuilder->setParameter('current_user', json_encode([['id' => $user->getId()]]));
这绝对可以帮助其他人完成它。
干杯!
拜托,我只是 querybuilder 的新手,确切地说我不知道如何在 where 子句中使用 json 对象。非常感谢您的 swift 帮助。
"post_id": 1
"post": ""
"author": [{"id": 2, "email": "example@example.com"}, {"id": 3, "email": "example2@example.com"}]
"post_id": 2
"post": ""
"author": [{"id": 4, "email": "example@example.com"}, {"id": 9, "email": "example2@example.com"}]
我想查询作者->id 为current_user的tablePost。我已经尽力了。我已经安装了 composer require scienta/doctrine-json-functions
当我运行它的时候,我得到了
"An exception occurred while executing a query: SQLSTATE[42883]: Undefined function: 7 ERROR: operator does not exist: json = unknown\nLINE 1: ... w0_ WHERE json_extract_path(w0_.author, ) = ORDER...\n ^\nHINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.",
我没主意了。
private function addWhere(QueryBuilder $queryBuilder, string $resourceClass): void
{
if (WorkshopSession::class !== $resourceClass || $this->security->isGranted('ROLE_ADMIN') || null === $user = $this->security->getUser()) {
return;
}
$rootAlias = $queryBuilder->getRootAliases()[0];
$queryBuilder->andWhere("JSON_EXTRACT_PATH(o.author, :id) = :current_user");
$queryBuilder->setParameter('id', 'o.id');
$queryBuilder->setParameter('current_user', $user->getId());
}
我正在使用 api 平台并使用学说扩展。数据库服务器 - postgreSQL
您需要做的第一件事是将选项切换到 jsonb,这将帮助您轻松遍历 json 树,而无需将自己置于框内。
select * from post where author @> '[{"id": "2"}]';
运行 这在您的传统 sql 中应该有效,然后将其转换为 DQL。这可能很棘手,因为 DQL 中没有“@>”,但您可以利用自定义 DQL 用户定义函数。我建议这样做而不是安装第三方库,因为第三方库会增加抽象层和版本控制问题(弃用)的复杂性。 正如您在下面看到的,我们使用了 FunctionNode、SqlWalker、Lexer 和 Parser。
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\SqlWalker;
use Doctrine\ORM\Query\AST\Node;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\Lexer;
use function sprintf;
class JsonContains extends FunctionNode
{
/** @var Node */
/** @psalm-suppress all */
private $expr1;
/** @var Node */
/** @psalm-suppress all */
private $expr2;
public function parse(Parser $parser) : void
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->expr1 = $parser->StringPrimary();
$parser->match(Lexer::T_COMMA);
$this->expr2 = $parser->StringPrimary();
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
public function getSql(SqlWalker $sqlWalker) : string
{
return sprintf(
'(%s @> %s)',
$this->expr1->dispatch($sqlWalker),
$this->expr2->dispatch($sqlWalker)
);
}
}
一旦你定义了这个,你就可以注册它。 Symfony 5 以上建议使用 doctrine.yaml。您可以通过以下方式注册
dql:
string_functions:
JSON_CONTAINS: App\Doctrine\Extension\Functions\DQL\UDF\JsonContains
然后在你的扩展中,你可以简单地使用它。
$queryBuilder->andWhere("JSON_CONTAINS(".$rootAlias .".author, :current_user) = true");
$queryBuilder->setParameter('current_user', json_encode([['id' => $user->getId()]]));
这绝对可以帮助其他人完成它。
干杯!