2015-04-29 19 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