0

Does anyone know how to create index on following JSON data in PostgreSQL 9.3?

Example data:

{
  {"1111" : "aaaa"},
  {"2222" : "bbbb"},
  {"3333" : "cccc"}
}

Say if I want to index on all the keys how to do that?

Thanks.

6
  • In 9.3, you can't create a general purpose index on json. Use hstore or wait for 9.4. You can make specific functional indexes, but for that you'd have to explain what you need to do. Commented Feb 11, 2014 at 11:47
  • I need to implement a trigram index on the data::json field so that the ilike query can execute fast as i need to search on key of this json and this can be arbitrary. select <json_field> from <table> where <json_field> ilike '%11111%'" ; Commented Feb 11, 2014 at 14:31
  • So you don't actually care about whether you're matching keys or values? You just want to search the whole json text as-is for a pattern? Commented Feb 11, 2014 at 22:37
  • Basically i want to search pattern in key of JSON, but here key is arbitrary. Commented Feb 12, 2014 at 4:42
  • Be specific, describe what you want like you were describing it to the database. Commented Feb 12, 2014 at 6:11

1 Answer 1

1

You haven't clearly defined what you want; here's what I'm assuming you mean:

Create an index that lets me test whether any given json value (example above) contains a key named 'k'

I think this is only possible (sanely) in 9.3 if the json structure is uniform, i.e. you always have an array of flat objects. If that's the case you can extract an array of keys, e.g.

regress=> create table x as select '[
  {"1111" : "aaaa"},
  {"2222" : "bbbb"},
  {"3333" : "cccc"}
]'::json as col;
SELECT 1

regress=> select array_agg(k) from x, lateral json_array_elements(col) e, lateral json_object_keys(e) k;
    array_agg     
------------------
 {1111,2222,3333}
(1 row)

and wrap that up in an SQL function:

CREATE OR REPLACE FUNCTION json_array_object_keys(json) RETURNS text[] AS $$
select array_agg(k) FROM lateral json_array_elements($1) e, lateral json_object_keys(e) k;
$$ LANGUAGE sql IMMUTABLE;

which works as follows:

craig=> SELECT json_array_object_keys(col) from x;
 json_array_object_keys 
------------------------
 {1111,2222,3333}
(1 row)

Then create a GIN array index on the expression:

CREATE INDEX json_nested_keys_idx ON x USING GIN( json_array_object_keys(col) );

(warning, such an index will be very slow to update, it will slow down insert/update/delete a lot)

and use it as follows:

SELECT * FROM x WHERE json_array_object_keys(col) @> ARRAY['1111'];

You can't do indexed searches for LIKE with the array approach; you'd have to squish the array into a text literal:

CREATE OR REPLACE FUNCTION json_array_object_keys_delim(json) RETURNS text AS $$
select array_to_string(array_agg(k),'|') FROM lateral json_array_elements($1) e, lateral json_object_keys(e) k;
$$ LANGUAGE sql IMMUTABLE;

CREATE INDEX json_tgrm_keys_idx ON x USING GiST( (json_array_object_keys_delim(col)) gist_trgm_ops);

SELECT * FROM x WHERE json_array_object_keys_delim(col) LIKE '%111%';
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.