Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 用JSONB数据查询Postgres表_Sql_Ruby On Rails_Postgresql_Jsonb - Fatal编程技术网

Sql 用JSONB数据查询Postgres表

Sql 用JSONB数据查询Postgres表,sql,ruby-on-rails,postgresql,jsonb,Sql,Ruby On Rails,Postgresql,Jsonb,我有一个在JSONB列中存储数据的表 现在,我要做的是,查询该表,并获取记录,这些记录具有特定的键值 这很好: SELECT "documents".* FROM "documents" WHERE (data @> '{"type": "foo"}') 但是我想做的是,获取表中所有的行,这些行的类型是foo或bar 我试过这个: SELECT "documents".* FROM "documents" WHERE (data @> '{"type": ["foo", "bar"

我有一个在JSONB列中存储数据的表

现在,我要做的是,查询该表,并获取记录,这些记录具有特定的键值

这很好:

SELECT "documents".*
FROM "documents"
WHERE (data @> '{"type": "foo"}')
但是我想做的是,获取表中所有的行,这些行的类型是
foo
bar

我试过这个:

SELECT "documents".*
FROM "documents"
WHERE (data @> '{"type": ["foo", "bar"]}')
SELECT "documents".*
FROM "documents"
WHERE (data->'type' ?| array['foo', 'bar'])
但这似乎不起作用

我也试过:

SELECT "documents".*
FROM "documents"
WHERE (data @> '{"type": ["foo", "bar"]}')
SELECT "documents".*
FROM "documents"
WHERE (data->'type' ?| array['foo', 'bar'])
这是可行的,但是如果我指定一个像so
data->'type'
这样的键,它会破坏查询的动态性

顺便说一句,我在Postgres中使用RubyonRails,所以所有的查询都要经过
ActiveRecord
。这就是为什么:

Document.where("data @> ?", query)
如果我指定一个像so data->“type”这样的键,它会带走查询的动态性

我知道您在
data
列上有一个gin索引,定义如下:

CREATE INDEX ON documents USING GIN (data);
该索引适用于此查询:

EXPLAIN ANALYSE
SELECT "documents".*
FROM "documents"
WHERE data @> '{"type": "foo"}';

                                                          QUERY PLAN                                                          
------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on documents  (cost=30.32..857.00 rows=300 width=25) (actual time=0.639..0.640 rows=1 loops=1)
   Recheck Cond: (data @> '{"type": "foo"}'::jsonb)
   Heap Blocks: exact=1
   ->  Bitmap Index Scan on documents_data_idx  (cost=0.00..30.25 rows=300 width=0) (actual time=0.581..0.581 rows=1 loops=1)
         Index Cond: (data @> '{"type": "foo"}'::jsonb)
 Planning time: 7.928 ms
 Execution time: 0.841 ms
但这一次不行:

EXPLAIN ANALYSE
SELECT "documents".*
FROM "documents"
WHERE (data->'type' ?| array['foo', 'bar']);

                                                QUERY PLAN                                                 
-----------------------------------------------------------------------------------------------------------
 Seq Scan on documents  (cost=0.00..6702.98 rows=300 width=25) (actual time=31.895..92.813 rows=2 loops=1)
   Filter: ((data -> 'type'::text) ?| '{foo,bar}'::text[])
   Rows Removed by Filter: 299997
 Planning time: 1.836 ms
 Execution time: 92.839 ms
解决方案1。使用运算符
@>
两次,索引将用于两种情况:

EXPLAIN ANALYSE
SELECT "documents".*
FROM "documents"
WHERE data @> '{"type": "foo"}'
OR data @> '{"type": "bar"}';

                                                             QUERY PLAN                                                             
------------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on documents  (cost=60.80..1408.13 rows=600 width=25) (actual time=0.222..0.233 rows=2 loops=1)
   Recheck Cond: ((data @> '{"type": "foo"}'::jsonb) OR (data @> '{"type": "bar"}'::jsonb))
   Heap Blocks: exact=2
   ->  BitmapOr  (cost=60.80..60.80 rows=600 width=0) (actual time=0.204..0.204 rows=0 loops=1)
         ->  Bitmap Index Scan on documents_data_idx  (cost=0.00..30.25 rows=300 width=0) (actual time=0.144..0.144 rows=1 loops=1)
               Index Cond: (data @> '{"type": "foo"}'::jsonb)
         ->  Bitmap Index Scan on documents_data_idx  (cost=0.00..30.25 rows=300 width=0) (actual time=0.059..0.059 rows=1 loops=1)
               Index Cond: (data @> '{"type": "bar"}'::jsonb)
 Planning time: 3.170 ms
 Execution time: 0.289 ms
解决方案2。在
(数据->'type')
上创建附加索引:

解决方案3。事实上,这是解决方案1的一个变体,具有不同的条件格式,更便于客户端程序使用:

EXPLAIN ANALYSE
SELECT "documents".*
FROM "documents"
WHERE data @> any(array['{"type": "foo"}', '{"type": "bar"}']::jsonb[]);

                                                          QUERY PLAN                                                          
------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on documents  (cost=60.65..1544.20 rows=600 width=26) (actual time=0.803..0.819 rows=2 loops=1)
   Recheck Cond: (data @> ANY ('{"{\"type\": \"foo\"}","{\"type\": \"bar\"}"}'::jsonb[]))
   Heap Blocks: exact=2
   ->  Bitmap Index Scan on documents_data_idx  (cost=0.00..60.50 rows=600 width=0) (actual time=0.778..0.778 rows=2 loops=1)
         Index Cond: (data @> ANY ('{"{\"type\": \"foo\"}","{\"type\": \"bar\"}"}'::jsonb[]))
 Planning time: 2.080 ms
 Execution time: 0.304 ms
(7 rows)

阅读更多信息。

感谢您的回复@klin。解决方案1可以工作,但我正在考虑其他方法,因为Rails是API部分,可以有任何类型的请求,我不想进入解析参数。所以我想了一些更干净的方法,我觉得应该在那里,因为这只是一个基本的操作。你觉得呢?我知道你的意思,这就是我为什么写第二个解决方案的原因。没有更干净的了。是的,但是属性可以更改,它不总是类型,所以再次,解析会出现在图片中。谢谢@klin。解决方案3看起来很有希望。