Ecto"离开右边"使用片段查询

时间:2016-01-07 16:38:02

标签: elixir phoenix-framework ecto

我想使用postgres IN运算符(使用Ecto库)查询jsonb字段

此代码使用简单的=运算符:

from a in query, where: fragment("?->>'format' = ?", a.properties, "foo")

但我无法做出任何这些尝试:

from a in query, where: fragment("?->>'format' IN ?", a.properties, ["foo", "bar"])
from a in query, where: fragment("?->>'format' IN (?)", a.properties, ["foo", "bar"])
from a in query, where: fragment("?->>'format' IN ?", a.properties, "('foo', 'bar')"])

有什么想法吗?

2 个答案:

答案 0 :(得分:6)

除了Patrick的出色响应之外,请记住,您也只能将部分查询放入片段中。例如,您可以将其重写为:

from a in query, where: fragment("?->>'format', a.properties) in ["foo", "bar"]

如果将片段放在宏中,您甚至可以获得可读的语法:

defmacro jsonb_get(left, right) do
  quote do
    fragment("?->>?", unquote(left), unquote(right))
  end
end

现在:

from a in query, where: jsonb_get(a.properties, "format") in ["foo", "bar"]

答案 1 :(得分:5)

这与JSONB无关。 Ecto会将您的类型列表转换为Postgres ARRAY,但这不适用于IN运算符:

psql> SELECT 1 IN(ARRAY[1, 2, 3]);
ERROR:  operator does not exist: integer = integer[]

但是,您可以使用= ANY()检查该值是否包含在ARRAY中:

psql> SELECT 1 = ANY(ARRAY[1, 2, 3]);
 ?column?
----------
 t
(1 row)

您应该能够使用以下片段来实现与Ecto相同的内容:

fragment("?->>'format' = ANY(?)", u.properties, ["foo", "bar"])