2015-04-29 23 views
5

参考original stackoverflow question,我试图将gin索引应用于Postgres 9.4中的数组对象中的键,但是我没有得到第一个答案中所述的结果。在PostgreSQL中使用json数组中的索引

你能纠正错误吗?

我遵循的步骤已写在下面。

第1部分:创建表和索引

CREATE TABLE tracks (id serial, artists jsonb); 
CREATE INDEX tracks_artists_gin_idx ON tracks USING gin (artists); 
INSERT INTO tracks (id, artists) VALUES (1, '[{"name": "blink-182"}]'); 
INSERT INTO tracks (id, artists) VALUES (2, '[{"name": "The Dirty Heads"}, {"name": "Louis Richards"}]'); 

第2部分:查询

SELECT * FROM tracks WHERE artists @> '{"name": "The Dirty Heads"}'; 
id | artists 
----+--------- 
(0 rows) 

这个查询给出空的结果。
我也试过使用jsonb_path_ops GIN索引。

替代索引和查询:

DROP INDEX tracks_artists_gin_idx; 
CREATE INDEX tracks_artistnames_gin_idx ON tracks USING gin (artists jsonb_path_ops); 
SELECT * FROM tracks WHERE artists @> '{"name": "The Dirty Heads"}'; 
id | artists 
----+--------- 
(0 rows) 
+1

在你引用的例子中,我的答案中缺少数组层。现在已经解决了。 @ potatosalad的答案提供了解释。 –

+0

对于这个问题的未来观众,我发现这个链接http://stackoverflow.com/a/30592076/2405689,它展示了如何查询'jsonb'对象数组,类似于上面的查询所要完成的内容。 – ArchNoob

回答

7

original answer此特定示例jsonb缺少阵列层[]围绕非原始对象容纳查询。它已经被修复。

记录PostgreSQL的9.4.x jsonb Containment and Existence状态的行为:

的一般原则是,以结构和数据内容

所包含的对象必须包含对象匹配...

作为一个特例,一般的原则是,结构必须匹配,一个数组可能包含一个原始值

特殊的例外,可以让我们做到以下几点:

CREATE TABLE tracks (id serial, artistnames jsonb); 
CREATE INDEX tracks_artistnames_gin_idx ON tracks USING gin (artistnames); 
INSERT INTO tracks (id, artists) VALUES (1, '["blink-182"]'); 
INSERT INTO tracks (id, artists) VALUES (2, '["The Dirty Heads", "Louis Richards"]'); 

我们可以使用一般原理查询遏制:

SELECT * FROM tracks WHERE artistnames @> '["The Dirty Heads"]'; 
id |    artistnames    
----+--------------------------------------- 
    2 | ["The Dirty Heads", "Louis Richards"] 
(1 row) 

我们也可以使用查询来使用遏制由于阵列的特殊异常包含原语类型:

SELECT * FROM tracks WHERE artistnames @> '"The Dirty Heads"'; 
id |    artistnames    
----+--------------------------------------- 
    2 | ["The Dirty Heads", "Louis Richards"] 
(1 row) 

有4种原始类型,允许容纳和存在查询阵列上的工作:

  1. 布尔
  2. null

既然你在你的问题是处理嵌套在一个阵列内的物体所提到的例子中,我们没有资格获得上述特殊情况例外:

CREATE TABLE tracks (id serial, artists jsonb); 
CREATE INDEX tracks_artists_gin_idx ON tracks USING gin (artists); 
INSERT INTO tracks (id, artists) VALUES (1, '[{"name": "blink-182"}]'); 
INSERT INTO tracks (id, artists) VALUES (2, '[{"name": "The Dirty Heads"}, {"name": "Louis Richards"}]'); 

我们可以使用的一般原则为遏制查询

SELECT * FROM tracks WHERE artists @> '[{"name": "The Dirty Heads"}]'; 
id |       artists       
----+----------------------------------------------------------- 
    2 | [{"name": "The Dirty Heads"}, {"name": "Louis Richards"}] 
(1 row) 

对象不被视为基本类型,因此对于遏制下面的查询不符合的特例,因此不工作:

SELECT * FROM tracks WHERE artists @> '{"name": "The Dirty Heads"}'; 
id | artists 
----+--------- 
(0 rows) 
+0

@ErwinBrandstetter我原来的措辞不适合描述实际问题,并且无意中贬低你的答案(直到我看到自己被引用时才意识到)。我已经改变它以更好地反映实际发生的事情。 – potatosalad

+0

我们活着学习。现在非常好的答案。 :) –

+0

谢谢@ErwinBrandstetter和potatosalad – user2512324