我正在寻找一种方法来利用PostgreSQL JSON operators中的新Phalcon Framework。
一个简单的表格来演示:
CREATE TABLE "user"
(
id_user serial NOT NULL,
data json,
CONSTRAINT pk_user PRIMARY KEY (id_user)
)
以及在psql
中运行正常的查询:
select * from "user" where data->>'email' = 'john@example.com';
然而,当用于Phalcon model时:
$users = UserModel::query()
->where("data->>'email' = :email:")
->bind(['email' => 'john@example.com'])
->execute();
它会产生语法错误:
ERROR: Syntax error, unexpected token >, near to '>'email' = :email:', when parsing: SELECT [Pht\Cli\Model\UserModel].* FROM [Pht\Cli\Model\UserModel] WHERE data->>'email' = :email:
我猜这与PHQL parser无法处理语法有关。但问题仍然存在:如何在Phalcon中使用JSON查询?
我试图将JSON语法包装成Db\RawValue:
$users = UserModel::query()
->where(new RawValue("data->>'email' = 'john@example.com'"))
->execute();
但似乎它仅用于更新/插入:
ERROR: Conditions must be string
我总是可以写一个原始查询,但这显然不是可行的方法。也可以在Model::find
和Model::findAll
中使用语法。
答案 0 :(得分:1)
现在你可以使用内置的postgres函数json_extract_path_text:
UserModel::query()->where("json_extract_path_text(data, 'email') = :email:");
答案 1 :(得分:0)
查看是否有实现->>
运算符的基础函数,并使用它。您可以pg_operator
查找oprname
的{{1}};在那里,您将看到->>
识别基础功能。对于不同的数据类型组合,可能有多个条目,因此您必须选择正确的条目。如果需要,您可以oprcode
加入oprleft
和oprright
以获取类型名称。
那会给你一个临时的解决方法。更好的方法是避免尝试在框架中解析SQL,或修复其解析器以处理复杂的运算符。
答案 2 :(得分:0)
在深入研究源代码并阅读论坛之后,我找到了基于this forum post的非常好的解决方法。基本思想是使用自定义数据库函数语法,在执行查询之前捕获并解析特殊的虚拟函数:
UserModel::query()->where("PG_JSON_PATH(\"data->>'email'\") = :email:");
为了实现这个目的,我们需要一个专门的Postgres适配器(下面的那个也使用这个hack潜入子查询,就像在原帖中一样):
class Postgresql93 extends \Phalcon\Db\Adapter\Pdo\Postgresql
{
public function query($sqlStatement, $bindParams = null, $bindTypes = null)
{
$sqlStatement = $this->handle93syntax($sqlStatement);
return parent::query($sqlStatement, $bindParams, $bindTypes);
}
private function handle93syntax($sqlStatement)
{
$specials = join('|', ['SUB_QUERY', 'PG_JSON_PATH']);
$pattern = "/($specials)[\\s]*\\([\\s]*\\'(.*)\\'[\\s]*\\)/";
$sqlStatement = preg_replace_callback(
$pattern,
function(array $matches){
$content = str_replace("''", "'", $matches[2]);
return $content;
},
$sqlStatement
);
return $sqlStatement;
}
}
答案 3 :(得分:0)
根据Craig的回答,您可以在Postgres上执行此查询以查找您要查找的运算符以及要在查询中使用的等效oprcode:
例如:
SELECT oprcode FROM pg_operator WHERE oprname = '->>';
您将获得许多结果,使用适当的结果。
谢谢,