【问题标题】:Ecto "left IN right" query using a fragment使用片段的 Ecto“左进右”查询
【发布时间】:2016-01-08 17:57:04
【问题描述】:

我想使用 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')"])

有什么想法吗?

【问题讨论】:

  • 您看到的确切错误/问题是什么?
  • 一个(丑陋的)似乎可行的事情是预先生成术语列表,然后将它们放入查询中:list = Enum.join(["foo", "bar"], ","); from a in query, where: fragment("?->>'format' IN (?)", a.properties, ^list])

标签: elixir phoenix-framework ecto


【解决方案1】:

除了 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"]

【讨论】:

  • 哦,非常好!得去重构一些查询;-)
  • 太好了,谢谢! Ecto 查询很强大,但有时对我来说似乎有点太神奇了:)
  • 非常酷!没想到你可以嵌入这样的片段。
【解决方案2】:

这与 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"])

【讨论】:

  • 确实,我可以在日志消息中看到我的列表已转换为 Postgres 数组,但我不知道该怎么做。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-31
相关资源
最近更新 更多