没有括号的Ecto片段

时间:2018-05-04 14:53:23

标签: postgresql ecto jsonb

我的Postgres表结构:

   id   | stuff                                                                                                                                                                                                        
--------+------------------------------------------------------------
  123   | {"type1": {"ref": "ref_1", "...": "..."}, "type2": {"ref": "ref_1", "...": "..."}}

我想通过ref在每种类型的东西中查询,我有一个有效的SQL查询:

SELECT * FROM "stuff" AS c0 CROSS JOIN jsonb_each(c0."stuff") AS f1 WHERE value->>'ref' = 'ref_1';

但是使用这个Ecto查询:

(from c in Stuff,
  join: fragment("jsonb_each(?)", c.stuff),
  where: fragment("value->>'ref' = ?", ^ref)
)
|> Repo.all

我在CROSS JOIN语句中遇到Postgres语法错误:

** (Postgrex.Error) ERROR 42601 (syntax_error): syntax error at or near ")"

检查生成的查询:

[debug] QUERY ERROR source="stuff" db=0.3ms
SELECT ... FROM "stuff" AS c0 CROSS JOIN (jsonb_each(c0."stuff")) AS f1 WHERE (value->>'ref' = $1) ["ref_1"]

当我删除(jsonb_each(c0."stuff"))周围的外括号时,上述方法有效。

有没有办法让片段在没有这些括号的情况下生成查询,还是我必须重新设计查询?

由于

2 个答案:

答案 0 :(得分:1)

似乎Ecto总是将join子句包装在括号中,这通常很好。不幸的是,它包括某些调用,如上面的jsonb_each。这种情况有一个维基:The parentheses rules of PostgreSQL, is there a summarized guide?

链接的原始sql示例有一个更少的upvoted答案,似乎适用于进行此查询并返回预期的结构。

sql = "SELECT * FROM "stuff" AS c0 CROSS JOIN jsonb_each(c0."stuff") AS f1 WHERE value->>'ref' = 'ref_1';"
result = JsonbTest.Repo.query!(sql)
Enum.map(result.rows, &JsonbTest.Repo.load(StuffStruct, {result.columns, &1}))

答案 1 :(得分:1)

这是ecto中的一个错误,已修复此处https://github.com/elixir-ecto/ecto/issues/2537