0

我有一个具有JSONB列contentPage模型的Rails 5项目。因此,结构看起来像这样(降低到最低限度的问题):在Rails中的JSONB查询包含哈希数组的键

#<Page id: 46, content: {..., "media" => [{ "resource_id" => 143, "other_key" => "value", ...}, ...], ...}> 

我将如何编写一个查询发现,有一些所需数量的resource_idcontent JSONB的media键下的所有网页柱?这是我做了一个不起作用的尝试(我认为是因为在阵列的每个项目中还有其他键/值对): Page.where("content -> 'media' @> ?", {resource_id: '143'}.to_json)

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

回答

2

使用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)); 

PostgreSQL有一个名为ANY(postgres docs)功能,采用的形式expression operator ANY (array)。使用给定的运算符评估左侧表达式并与数组的每个元素进行比较。

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

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

+0

谢谢,这是非常有帮助的。使用Rails而不是直接SQL,我编写了这个查询,它给了我所需要的: 'Page.where(“'{\”resource_id \“:?}'<@ ANY(ARRAY(select jsonb_array_elements(content - >) 'media')))“,143)' – Lee