我想使用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')"])
有什么想法吗?
答案 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"])