我有一个非常简单的 JSON 表,其中填充了一些示例数据:
CREATE TABLE jsonthings(d JSONB NOT NULL);
INSERT INTO jsonthings VALUES ('{"name":"First","tags":["foo"]}');
INSERT INTO jsonthings VALUES ('{"name":"Second","tags":["foo","bar"]}');
INSERT INTO jsonthings VALUES ('{"name":"Third","tags":["bar","baz"]}');
INSERT INTO jsonthings VALUES ('{"name":"Fourth","tags":["baz"]}');
CREATE INDEX ON jsonthings USING GIN(d);
并且在运行SELECT
. 一个简单SELECT
的获取值为单个项目的行就可以了:
SELECT d FROM jsonthings WHERE d @> '{"name":"First"}';
但是,当尝试运行与多个值匹配的查询时,name
我不知道如何使用索引。我试过了:
SELECT d FROM jsonthings WHERE d->>'name' = ANY(ARRAY['First', 'Second']);
SELECT d FROM jsonthings WHERE d->'name' ?| ARRAY['First', 'Second'];
SELECT d FROM jsonthings WHERE d#>'{name}' ?| ARRAY['First','Second'];
并且它们都显示了对表的顺序扫描(如果可能的话,我enable_seqscan=false
用来强制使用索引)。有什么方法可以重写查询以使其使用索引?我知道我可以这样做:
SELECT * FROM jsonthings WHERE d @> '{"name":"First"}' OR d @> '{"name":"Second"}';
但是后来我有一个可变长度的查询,并且我正在通过 JDBC,所以会失去查询作为 PreparedStatement 的好处。
我也有兴趣看到针对tags
密钥中许多项目中的任何一个的类似查询,例如:
SELECT d FROM jsonthings WHERE d @> '{"tags":["foo"]}' OR d @> '{"tags":["bar"]}';
但是使用一个ARRAY
而不是多个条件并使用一个索引。
这是在 PostgreSql 9.4 上。
这是对 Mladen 提供的答案的回应。我没有足够的声誉来发表评论,但我想回复,因为看起来查询可能不正确,并且让我感到困惑,并且将来可能会导致其他人感到困惑。
你提到使用:
First
但是,要检索具有或作为名称的任何条目Second
,这似乎对我不起作用PostgreSQL 9.4.4
:似乎上面的查询正在尝试检索
name
属性包含数组的条目["First", "Second"]
。如果我创建这样一个条目:
然后再次尝试查询,它返回一个结果:
name
但是,这与原始发帖人提出的问题不同,即在查询属性为First
or 的条目时如何使用索引Second
:我想在这里提供这个,所以其他人认为不可能通过提供 JSON来执行OR
"name": ["First", "Second"]
查询,因为它具有误导性。从文档(http://www.postgresql.org/docs/9.4/static/datatype-json.html)尝试使用表达式索引: