如何将此 jsonb SQL 查询转换为 Active Record 查询?

How to translate this jsonb SQL query to an Active Record query?

我的 Color ActiveRecord 模型中存在以下数据:

id colored_things
1 [{"thing" : "cup", "color": "red"}, {"thing" : "car", "color": "blue"}]
2 [{"thing" : "other", "color": "green"}, {"thing" : "tile", "color": "reddish"}]
3 [{"thing" : "unknown", "color": "red"}]
4 [{"thing" : "basket", "color": "velvet or red or purple"}]

colored_things列定义为jsonb。

我正在尝试搜索所有 "color" 键以获取 类似于 特定搜索词的值。这个 SQL 查询(参见 SQL Fiddle)是这样做的:

SELECT DISTINCT C.*
FROM colors AS C,
jsonb_array_elements(colored_things) AS colorvalues(colorvalue)
WHERE colorvalue->>'color' ILIKE '%pur%';

现在我很想将此查询转换为适当的 Active Record 查询,但以下内容不起作用:

Color.joins(jsonb_array_elements(colored_things) AS colorvalues(colorvalue))
  .where("colorvalue->>'color' ILIKE '%?%'", some_search_term)
  .distinct

这给了我错误:

ActiveRecord::StatementInvalid (PG::UndefinedTable: ERROR: invalid reference to FROM-clause entry for table "colors")

有人能给我指出正确的方向吗?

如果您使用 ActiveRecord,情况不会有太大变化,而且如果您将查询保留在 SQL.

中,IMO 仍然更具可读性

为了让它工作,你可以使用 from,然后传递你当前拥有的 raw FROM 子句:

from("colors AS c, JSONB_ARRAY_ELEMENTS(colored_things) AS colorvalues(colorvalue)")

如果您的表和别名已经可以访问,那么您可以将 WHERESELECT 子句与其相应的 AR 方法链接起来:

Color
  .from("colors AS c, JSONB_ARRAY_ELEMENTS(colored_things) AS colorvalues(colorvalue)")
  .where("colorvalue->>'color' ILIKE '%pur%'")
  .select("DISTINCT c.*")

注意 where("colorvalue->>'color' ILIKE '%?%'", value) 将不起作用,因为 value 被 ORM 引用,因此您必须构造 "%value%" 并将其用作绑定值:

where("colorvalue->>'color' ILIKE ?", "%#{value}%")