ruby-on-rails - 为 jsonb 值搜索构建 Activerecord/SQL 查询

标签 ruby-on-rails ruby postgresql activerecord jsonb

目前,对于使用不同参数的重复搜索,我构建了此 ActiveRecord 查询:

current_user.documents.order(:updated_at).reverse_order.includes(:groups,:rules)

现在,通常我会添加一个 where 子句来执行此搜索。但是,我现在需要通过 jsonb 字段搜索具有特定 (如键:值对)的所有行。我已经能够使用以下语法执行类似于 SQL 中的操作(数据字段将仅精确嵌套两层):

SELECT 
    * 
FROM 
    (SELECT 
         * 
    FROM 
        (SELECT 
            * 
        FROM 
            documents
        ) A, 
        jsonb_each(A.data)
    ) B, 
    jsonb_each_text(B.value) ASC C 
WHERE 
    C.value = '30';

但是,我想使用当前的 ActiveRecord 搜索来进行此查询(其中包括组/规则预加载)。

我正在努力使用逗号,我理解这是一个隐式连接,它在显式连接之前执行,所以当我尝试这样的事情时:

select * from documents B join (select * from jsonb_each(B.data)) as A on true;
ERROR:  invalid reference to FROM-clause entry for table "b"
LINE 1: ...* from documents B join (select * from jsonb_each(B.data)) a...
                                                           ^
HINT: There is an entry for table "b", but it cannot be referenced from this part of the query.

但我不明白如何在进行联接调用之前引用我创建的 ActiveRecord 查询的完整“表”,以及如何使用逗号语法使隐式联接发挥作用。

另外,我是一名 SQL 业余爱好者,所以如果您看到一些改进或其他方法来做到这一点,请告诉我们。

编辑:文档表说明:

enter image description here

                                                        Table "public.documents"
Column      |            Type             |                       Modifiers                        | Storage  | Stats target | Description 
------------+-----------------------------+--------------------------------------------------------+----------+--------------+-------------
id          | integer                     | not null default nextval('documents_id_seq'::regclass) | plain    |              | 
document_id | character varying           |                                                        | extended |              | 
name        | character varying           |                                                        | extended |              | 
size        | integer                     |                                                        | plain    |              | 
last_updated| timestamp without time zone |                                                        | plain    |              | 
user_id     | integer                     |                                                        | plain    |              | 
created_at  | timestamp without time zone |                                                        | plain    |              | 
updated_at  | timestamp without time zone |                                                        | plain    |              | 
kind        | character varying           |                                                        | extended |              | 
uid         | character varying           |                                                        | extended |              | 
access_token_id | integer                     |                                                        | plain    |              | 
data        | jsonb                       | not null default '{}'::jsonb                           | extended |              | 

索引: “documents_pkey”主键,btree(id) ````

示例行,首先匹配搜索“30”(数据是最后一个字段):

2104 | 24419693037                                          | LsitHandsBackwards.jpg                   |        |                         |       1 | 2017-06-25 21:45:49.121686 | 2017-07-01 21:32:37.624184 | box          | 221607127         |              15 | {"owner": {"born": "to make history", "price": 30}}
2177 | /all-drive/uml flows/typicaluseractivity.svg         | TypicalUserActivity.svg                  |  12375 | 2014-08-11 02:21:14     |       1 | 2017-07-07 14:00:11.487455 | 2017-07-07 14:00:11.487455 | dropbox      | 325694961         |              20 | {"owner": {}}

最佳答案

您可以使用与您已经展示的查询类似的查询:

SELECT
    d.id, d.data
FROM
    documents AS d 
    INNER JOIN json_each(d.data)  AS x ON TRUE 
    INNER JOIN json_each(x.value) AS y ON TRUE 
WHERE
    cast(y.value as text) = '30';

假设您的数据如下:

INSERT INTO documents
    (data)
VALUES
   ('{"owner": {"born": "to make history", "price": 30}}'),
   ('{"owner": {}}'),
   ('{"owner": {"born": "to make history", "price": 50}, "seller": {"worth": 30}}')
;

您得到的结果是:

id | data                                                                        
-: | :---------------------------------------------------------------------------
 1 | {"owner": {"born": "to make history", "price": 30}}                         
 3 | {"owner": {"born": "to make history", "price": 50}, "seller": {"worth": 30}}

您可以在 dbfiddle here 上检查它(以及一些逐步查看数据)。

关于ruby-on-rails - 为 jsonb 值搜索构建 Activerecord/SQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44999082/

相关文章:

ruby-on-rails - Rails to_json :methods that have parameters

ruby-on-rails - 如何优雅地重启 thin + nginx?

ruby-on-rails - <%%= 在 Ruby on Rails 中是什么意思?

mysql - rails : auto increment column with scope

ruby-on-rails - #to_s 会失败吗?

ruby-on-rails - 让 'form_for(@something)' 在 new.html.erb 之外工作

ruby-on-rails - 我如何让 Rails 在我运行测试时加载我的测试环境变量?

ruby-on-rails - 多个字段的唯一索引......但不是你想的那样

python - Docker 公开容器之间的端口

SQL - 以列值作为列名的聚合