Rails 中的 JSONB 查询包含哈希数组的键

Lee*_*Lee 3 postgresql activerecord ruby-on-rails jsonb ruby-on-rails-5

我有一个 Rails 5 项目,其Page模型具有 JSONB 列content。所以结构看起来像这样(减少到问题的最低限度):

#<Page id: 46, content: {..., "media" => [{ "resource_id" => 143, "other_key" => "value", ...}, ...], ...}>
Run Code Online (Sandbox Code Playgroud)

我将如何编写一个查询来查找在 JSONB 列的键下具有resource_id某个所需数字的所有页面?这是我所做的尝试,但不起作用(我认为是因为数组的每个项目中还有其他键/值对): mediacontentPage.where("content -> 'media' @> ?", {resource_id: '143'}.to_json)

编辑:这有效,但只会检查媒体数组中的第一个哈希:Page.where("content -> 'media' -> 0 ->> 'resource_id' = ?", '143')

Reu*_*eub 5

使用 sql,这应该为您提供资源 ID 为 143 的所有页面:

select * from pages p where '{"resource_id": 143}' <@ ANY ( ARRAY(select jsonb_array_elements ( content -> 'media' ) from pages where id=p.id ) );
Run Code Online (Sandbox Code Playgroud)

Postgresql 有一个名为 ANY 的函数(postgres 文档),它使用以下形式expression operator ANY (array)。使用给定运算符对左侧表达式进行求值并与数组的每个元素进行比较。

由于 ANY 的右侧参数必须是数组(而不是 json 数组),因此我们使用 jsonb_array_elements 方法将 content->media json 数组转换为一组行,然后使用 ARRAY( )。

<@运算符检查右侧的表达式是否包含左侧的表达式。例如:'{"a": 1}'::jsonb <@ '{"b": 2, "a": 1}'::jsonb将返回 true。