From 0b92a77c17ebe8bec08e250e1a929b07efef1008 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 9 May 2014 16:33:25 -0400 Subject: [PATCH] Improve user-facing JSON documentation. I started out with the intention of just fixing the info about the jsonb operator classes, but soon found myself copy-editing most of the JSON material. Hopefully it's more readable now. --- doc/src/sgml/func.sgml | 216 ++++++++++----------- doc/src/sgml/gin.sgml | 2 +- doc/src/sgml/json.sgml | 340 ++++++++++++++++------------------ doc/src/sgml/release-9.3.sgml | 4 +- 4 files changed, 261 insertions(+), 301 deletions(-) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 5126f14eb6..8a10eb30cb 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -10081,7 +10081,7 @@ table2-mapping JSON - Functions and operators + functions and operators @@ -10105,43 +10105,43 @@ table2-mapping -> - int + int Get JSON array element '[{"a":"foo"},{"a":"bar"},{"a":"baz"}]'::json->2 {"a":"baz"} -> - text + text Get JSON object field '{"a": {"b":"foo"}}'::json->'a' {"b":"foo"} ->> - int - Get JSON array element as text + int + Get JSON array element as text '[1,2,3]'::json->>2 3 ->> - text - Get JSON object field as text + text + Get JSON object field as text '{"a":1,"b":2}'::json->>'b' 2 #> - text[] + text[] Get JSON object at specified path '{"a": {"b":{"c": "foo"}}}'::json#>'{a,b}' {"c": "foo"} #>> - text[] - Get JSON object at specified path as text + text[] + Get JSON object at specified path as text '{"a":[1,2,3],"b":[4,5,6]}'::json#>>'{a,2}' 3 @@ -10152,14 +10152,17 @@ table2-mapping There are parallel variants of these operators for both the - json and jsonb types. In addition to - those operators common to both types, a further set of operators - exists for jsonb (which comprise the default - GIN operator class). + json and jsonb types. The operators + return the same type as their left-hand input (either json + or jsonb), except for those specified as + returning text, which coerce the value to text. - The following are jsonb-only operators, used by + In addition to those operators common to both types, some additional + operators exist only for jsonb, as shown + in . + Many of these operators can be indexed by jsonb operator classes. For a full description of jsonb containment semantics and nesting, see . @@ -10167,7 +10170,7 @@ table2-mapping jsonb. - Additonal JSONB Operators + Additional <type>jsonb</> Operators @@ -10180,37 +10183,38 @@ table2-mapping = - jsonb - Is the jsonb equal to this jsonb? + jsonb + Are the two JSON values equal? '[1,2,3]'::jsonb = '[1,2,3]'::jsonb @> - jsonb - Does the jsonb contain within it this jsonb? + jsonb + Does the left JSON value contain within it the right value? '{"a":1, "b":2}'::jsonb @> '{"b":2}'::jsonb <@ - jsonb - Does the jsonb have contained within it this jsonb? + jsonb + Is the left JSON value contained within the right value? '{"b":2}'::jsonb <@ '{"a":1, "b":2}'::jsonb ? - text - Does this key/element string exist? + text + Does the key/element string exist within + the JSON value? '{"a":1, "b":2}'::jsonb ? 'b' ?| - text[] + text[] Do any of these key/element strings exist? '{"a":1, "b":2, "c":3}'::jsonb ?| array['b', 'c'] ?& - text[] + text[] Do all of these key/element strings exist? '["a", "b"]'::jsonb ?& array['a', 'b'] @@ -10218,15 +10222,11 @@ table2-mapping
- - + shows the functions that are available for creating json values. - (see ) + (Currently, there are no equivalent functions for jsonb, but you + can cast the result of one of these functions to jsonb.) @@ -10250,11 +10250,10 @@ table2-mapping JSON Creation Functions - + Function - Return Type Description Example Example Result @@ -10265,7 +10264,6 @@ table2-mapping array_to_json(anyarray [, pretty_bool]) - json Returns the array as JSON. A PostgreSQL multidimensional array becomes a JSON array of arrays. Line feeds will be added between @@ -10278,7 +10276,6 @@ table2-mapping row_to_json(record [, pretty_bool]) - json Returns the row as JSON. Line feeds will be added between level 1 elements if pretty_bool is true. @@ -10290,7 +10287,6 @@ table2-mapping to_json(anyelement) - json Returns the value as JSON. If the data type is not built in, and there is a cast from the type to json, the cast function will be used to @@ -10305,43 +10301,29 @@ table2-mapping json_build_array(VARIADIC "any") - json - Builds a heterogeneously-typed json array out of a variadic argument list. - - SELECT json_build_array(1,2,'3',4,5); - - - json_build_array -------------------- - [1, 2, "3", 4, 5] - + Builds a possibly-heterogeneously-typed JSON array out of a variadic + argument list. + json_build_array(1,2,'3',4,5) + [1, 2, "3", 4, 5] json_build_object(VARIADIC "any") - json - Builds a JSON array out of a variadic argument list. By - convention, the object is constructed out of alternating - name/value arguments. - - SELECT json_build_object('foo',1,'bar',2); - - - json_build_object ------------------------- - {"foo" : 1, "bar" : 2} - + Builds a JSON object out of a variadic argument list. By + convention, the argument list consists of alternating + names and values. + json_build_object('foo',1,'bar',2) + {"foo" : 1, "bar" : 2} json_object(text[]) - json Builds a JSON object out of a text array. The array must have either exactly one dimension with an even number of members, in which case @@ -10349,42 +10331,28 @@ table2-mapping such that each inner array has exactly two elements, which are taken as a name/value pair. - select * from json_object('{a, 1, b, "def", c, 3.5}') or select json_object('{{a, 1},{b, "def"},{c, 3.5}}') - - - json_object ---------------------------------------- - {"a" : "1", "b" : "def", "c" : "3.5"} - - + json_object('{a, 1, b, "def", c, 3.5}') + json_object('{{a, 1},{b, "def"},{c, 3.5}}') + {"a" : "1", "b" : "def", "c" : "3.5"} json_object(keys text[], values text[]) - json - The two-argument form of JSON object takes keys and values pairwise from two separate + This form of json_object takes keys and values pairwise from two separate arrays. In all other respects it is identical to the one-argument form. - select json_object('{a, b}', '{1,2}'); - - - json_object ------------------------- - {"a" : "1", "b" : "2"} - - + json_object('{a, b}', '{1,2}') + {"a" : "1", "b" : "2"}
- shows the functions that are available for processing json and jsonb values. - (see ) @@ -10494,8 +10462,8 @@ table2-mapping json_each(json) jsonb_each(jsonb) - SETOF key text, value json - SETOF key text, value jsonb + setof key text, value json + setof key text, value jsonb Expands the outermost JSON object into a set of key/value pairs. @@ -10514,10 +10482,10 @@ table2-mapping json_each_text(from_json json) jsonb_each_text(from_json jsonb) - SETOF key text, value text + setof key text, value text Expands the outermost JSON object into a set of key/value pairs. The - returned value will be of type text. + returned value will be of type text. select * from json_each_text('{"a":"foo", "b":"bar"}') @@ -10556,7 +10524,7 @@ table2-mapping json_object_keys(json) jsonb_object_keys(jsonb) - SETOF text + setof text Returns set of keys in the JSON object. Only the outer object will be displayed. @@ -10595,7 +10563,7 @@ table2-mapping json_populate_recordset(base anyelement, from_json json, [, use_json_as_text bool=false]) jsonb_populate_recordset(base anyelement, from_json jsonb, [, use_json_as_text bool=false]) - SETOF anyelement + setof anyelement Expands the outermost set of objects in from_json to a set whose columns match the record type defined by base. @@ -10618,13 +10586,13 @@ table2-mapping json_array_elements(json) jsonb_array_elements(jsonb) - SETOF json - SETOF jsonb + setof json + setof jsonb Expands a JSON array to a set of JSON values. - SELECT * FROM json_array_elements('[1,true, [2,false]]') + select * from json_array_elements('[1,true, [2,false]]') value @@ -10639,11 +10607,11 @@ table2-mapping json_array_elements_text(json) jsonb_array_elements_text(jsonb) - SETOF text + setof text - Expands a JSON array to a set of text values. + Expands a JSON array to a set of text values. - SELECT * FROM json_array_elements_text('["foo", "bar"]') + select * from json_array_elements_text('["foo", "bar"]') value @@ -10674,9 +10642,9 @@ table2-mapping record Returns an arbitrary record from a JSON object. As with all functions - returning 'record', the caller must explicitly define the structure of the record + returning record, the caller must explicitly define the structure of the record when making the call. The input JSON must be an object, not a scalar or an array. - If nested_as_text is true, the function coerces nested complex elements to text. + If nested_as_text is true, the function coerces nested complex elements to text. Also, see notes below on columns and types. select * from json_to_record('{"a":1,"b":[1,2,3],"c":"bar"}',true) as x(a int, b text, d text) @@ -10695,9 +10663,9 @@ table2-mapping setof record Returns an arbitrary set of records from a JSON object. As with - json_to_record, the structure of the record must be explicitly defined when making the - call. However, with json_to_recordset the input JSON must be an array containing - objects. nested_as_text works as with json_to_record. + json_to_record, the structure of the record must be explicitly defined when making the + call. However, with json_to_recordset the input JSON must be an array containing + objects. nested_as_text works as with json_to_record. select * from json_to_recordset('[{"a":1,"b":"foo"},{"a":"2","c":"bar"}]',true) as x(a int, b text); @@ -10715,56 +10683,60 @@ table2-mapping - The json functions and operators can impose stricter validity requirements - than the type's input functions. In particular, they check much more closely that any use - of Unicode surrogate pairs to designate characters outside the Unicode Basic Multilingual - Plane is correct. + The json functions and operators can impose stricter + validity requirements than the JSON types' input functions do. In + particular, they check much more closely that any use of Unicode + surrogate pairs to designate characters outside the Unicode Basic + Multilingual Plane is correct. - Many of these functions and operators will convert Unicode escapes - in the JSON text to the appropriate UTF8 character when the database encoding is UTF8. In - other encodings the escape sequence must be for an ASCII character, and any other code point - in a Unicode escape sequence will result in an error. - In general, it is best to avoid mixing Unicode escapes in JSON with a non-UTF8 database - encoding, if possible. + Many of these functions and operators will convert Unicode escapes in + the JSON text to the appropriate UTF8 character when the database + encoding is UTF8. In other encodings the escape sequence must be for an + ASCII character, and any other code point in a Unicode escape sequence + will result in an error. In general, it is best to avoid mixing Unicode + escapes in JSON with a non-UTF8 database encoding, if possible. - In json_to_record and json_to_recordset, type-coercion from the JSON is - "best effort" and may not result in desired values for some types. JSON - elements are matched to identical field names in the record definition, - and elements which do not exist in the JSON will simply be NULL. JSON - elements which are not defined in the record template will - be omitted from the output. + In json_to_record and json_to_recordset, + type coercion from the JSON is best effort and may not result + in desired values for some types. JSON elements are matched to + identical field names in the record definition, and elements which do + not exist in the JSON will simply be NULL. JSON elements which are not + defined in the record template will be omitted from the output. - The extension has a cast from hstore to - json, so that converted hstore values are represented as JSON objects, + The extension has a cast + from hstore to json, so that + converted hstore values are represented as JSON objects, not as string values. - The json_typeof function's null return value should not be confused - with a SQL NULL. While calling json_typeof('null'::json) will return null, - calling json_typeof(NULL::json) will return a SQL NULL. + The json_typeof function's null return value + should not be confused with a SQL NULL. While + calling json_typeof('null'::json) will + return null, calling json_typeof(NULL::json) + will return a SQL NULL. - See also about the aggregate + See also for the aggregate function json_agg which aggregates record - values as JSON efficiently, and the aggregate function - json_object_agg, which aggregates pairs of values + values as JSON, and the aggregate function + json_object_agg which aggregates pairs of values into a JSON object. diff --git a/doc/src/sgml/gin.sgml b/doc/src/sgml/gin.sgml index 576ad3005a..41f7b91395 100644 --- a/doc/src/sgml/gin.sgml +++ b/doc/src/sgml/gin.sgml @@ -416,7 +416,7 @@ Of the two operator classes for type jsonb, jsonb_ops is the default. jsonb_hash_ops supports fewer operators but - will work with larger indexed values than jsonb_ops can support. + offers better performance for those operators. diff --git a/doc/src/sgml/json.sgml b/doc/src/sgml/json.sgml index 5fd2439742..592a5ce2b2 100644 --- a/doc/src/sgml/json.sgml +++ b/doc/src/sgml/json.sgml @@ -15,118 +15,148 @@ JSON data types are for storing JSON (JavaScript Object Notation) data, as specified in RFC 7159. Such data can also be stored as text, but - both JSON data types have the advantage of enforcing that each - stored value is a valid JSON value. There are also related support - functions available; see . + the JSON data types have the advantage of enforcing that each + stored value is valid according to the JSON rules. There are also + assorted JSON-specific functions available for data stored in these + data types; see . There are two JSON data types: json and jsonb. - Both accept almost identical sets of values as + They accept almost identical sets of values as input. The major practical difference is one of efficiency. The json data type stores an exact copy of the input text, - which processing functions must continually reparse, while + which processing functions must reparse on each execution; while jsonb data is stored in a decomposed binary format that - makes it slightly less efficient to input due to added serialization + makes it slightly slower to input due to added conversion overhead, but significantly faster to process, since it never needs - reparsing. jsonb also supports advanced - GIN indexing, which is a further significant - advantage. + reparsing. jsonb also supports indexing, which can be a + significant advantage. - The other difference between the types is that the json - type is guaranteed to contain an exact copy of the input, including - preservation of semantically insignificant white space, and the - order of keys within JSON objects (although jsonb will - preserve trailing zeros within a JSON number). Also, because the - exact text is kept, if a JSON object within the value contains the - same key more than once, and has been stored using the json - type, all the key/value pairs are kept. In that case, the - processing functions consider the last value as the operative one. - By contrast, jsonb does not preserve white space, does not - preserve the order of object keys, and does not keep duplicate - object keys. Only the last value for a key specified in the input - is kept. + Because the json type stores an exact copy of the input text, it + will preserve semantically-insignificant white space between tokens, as + well as the order of keys within JSON objects. Also, if a JSON object + within the value contains the same key more than once, all the key/value + pairs are kept. (The processing functions consider the last value as the + operative one.) By contrast, jsonb does not preserve white + space, does not preserve the order of object keys, and does not keep + duplicate object keys. Only the last value for a key specified in the + input is kept. jsonb will preserve trailing zeros within a JSON + number, even though those are semantically insignificant for purposes such + as equality checks. - In general, most applications will prefer to store JSON data as - jsonb, unless there are quite specialized needs. + In general, most applications should prefer to store JSON data as + jsonb, unless there are quite specialized needs, such as + legacy assumptions about ordering of object keys. - PostgreSQL allows only one server + PostgreSQL allows only one character set encoding per database. It is therefore not possible for the JSON - types to conform rigidly to the specification unless the server + types to conform rigidly to the JSON specification unless the database encoding is UTF-8. Attempts to directly include characters which - cannot be represented in the server encoding will fail; conversely, - characters which can be represented in the server encoding but not + cannot be represented in the database encoding will fail; conversely, + characters which can be represented in the database encoding but not in UTF-8 will be allowed. \uXXXX escapes are - allowed regardless of the server encoding, and are checked only for + allowed regardless of the database encoding, and are checked only for syntactic correctness. Mapping of RFC-7159/JSON Primitive Types to <productname>PostgreSQL</productname> Types - Mapping of type correspondence, notes + JSON scalar types and corresponding <productname>PostgreSQL</productname> types - PostgreSQL type RFC-7159/JSON primitive type + PostgreSQL type Notes - text string - See general introductory notes on encoding and JSON + text + See introductory notes on JSON and encoding - numeric number + numeric NaN and infinity values are disallowed boolean boolean - Only lowercase true and false values are accepted + Only lowercase true and false spellings are accepted - unknown null - SQL NULL is orthogonal. NULL semantics do not apply. + (none) + SQL NULL is a different concept
- Primitive types described by RFC 7159 are effectively - internally mapped onto native - PostgreSQL types. Therefore, there are + When converting textual JSON input into jsonb, + the primitive types described by RFC 7159 are effectively + mapped onto native + PostgreSQL types, as shown in + . Therefore, there are some very minor additional constraints on what constitutes valid jsonb that do not apply to the json - type, or to JSON in the abstract, that pertain to limits on what - can be represented by the underlying type system. These + type, nor to JSON in the abstract, corresponding to limits on what + can be represented by the underlying data type. Specifically, + jsonb will reject numbers that are outside the range of + the PostgreSQL numeric data type, + while json will not. Such implementation-defined restrictions are permitted by - RFC 7159. However, in practice problems are far more - likely to occur in other implementations which internally + RFC 7159. However, in practice such problems are far more + likely to occur in other implementations, as it is common to represent the number JSON primitive type as IEEE 754 - double precision floating point values, which RFC 7159 - explicitly anticipates and allows for. When using JSON as an + double precision floating point (which RFC 7159 + explicitly anticipates and allows for). When using JSON as an interchange format with such systems, the danger of losing numeric - precision in respect of data originally stored by + precision compared to data originally stored by PostgreSQL should be considered. - - Conversely, as noted above there are some minor restrictions on - the input format of JSON primitive types that do not apply to - corresponding PostgreSQL types. - + + Conversely, as noted in the table there are some minor restrictions on + the input format of JSON primitive types that do not apply to + the corresponding PostgreSQL types. + +
+ + + <type>jsonb</> Input and Output Syntax + + The input/output syntax for the JSON data types is as specified in + RFC 7159. + + + The following are all valid json (or jsonb) expressions: + +-- Simple scalar/primitive value (explicitly required by RFC-7159) +SELECT '5'::json; + +-- Array of heterogeneous, primitive-typed elements +SELECT '[1, 2, "foo", null]'::json; + +-- Object of heterogeneous key/value pairs of primitive types +-- Note that key values are always strings +SELECT '{"bar": "baz", "balance": 7.77, "active":false}'::json; + + + + Note the distinction between scalar/primitive values as array elements, + keys and values. + @@ -144,46 +174,19 @@ summarize a set of documents (datums) in a table.
- jsonb data is subject to the same concurrency control + json data is subject to the same concurrency control considerations as any other datatype when stored in a table. Although storing large documents is practicable, in order to ensure correct behavior row-level locks are, quite naturally, acquired as - rows are updated. Consider keeping jsonb documents at a + rows are updated. Consider keeping json documents at a manageable size in order to decrease lock contention among updating - transactions. Ideally, jsonb documents should each + transactions. Ideally, json documents should each represent an atomic datum that business rules dictate cannot reasonably be further subdivided into smaller atomic datums that can be independently modified. - - <type>jsonb</> Input and Output Syntax - - In effect, jsonb has an internal type system whose - implementation is defined in terms of several particular ordinary - PostgreSQL types. The SQL parser does - not have direct knowledge of the internal types that constitute a - jsonb. - - - The following are all valid jsonb expressions: - --- Simple scalar/primitive value (explicitly required by RFC-7159) -SELECT '5'::jsonb; --- Array of heterogeneous, primitive-typed elements -SELECT '[1, 2, "foo", null]'::jsonb; - --- Object of heterogeneous key/value pairs of primitive types --- Note that key values are always strings -SELECT '{"bar": "baz", "balance": 7.77, "active":false}'::jsonb; - - - - Note the distinction between scalar/primitive values as elements, - keys and values. - - <type>jsonb</> containment @@ -199,7 +202,7 @@ SELECT '{"bar": "baz", "balance": 7.77, "active":false}'::jsonb; technically, top-down, unordered subtree isomorphism may be tested. Containment is conventionally tested using the @> operator, which is made indexable by various - operator classes discussed later in this section. + operator classes discussed below.
-- Simple scalar/primitive values may contain only each other: @@ -249,45 +252,47 @@ SELECT '{"p":1, "a":{"b":3, "q":11}, "i":77}'::jsonb @> '{"a":{"b":3}}'::jsonb; The various containment operators, along with all other JSON - operators and support functions are documented fully within , . + operators and support functions are documented in . + - <type>jsonb</> GIN Indexing + <type>jsonb</> Indexing jsonb indexes on - - jsonb GIN indexes can be used to efficiently search among - more than one possible key/value pair within a single - jsonb datum/document, among a large number of such - documents within a column in a table (i.e. among many rows). - - - jsonb has GIN index support for the @>, - ?, ?& and ?| operators. - The default GIN operator class makes all these operators - indexable: - - --- GIN index (default opclass) -CREATE INDEX idxgin ON api USING GIN (jdoc); --- GIN jsonb_hash_ops index -CREATE INDEX idxginh ON api USING GIN (jdoc jsonb_hash_ops); - + jsonb GIN indexes can be used to efficiently search for + keys or key/value pairs occurring within a large number of + jsonb documents (datums). + Two GIN operator classes are provided, offering different + performance and flexibility tradeoffs. + + + The default GIN operator class supports queries with the + @>, ?, ?& and ?| + operators. + (For details of the semantics that these operators + implement, see .) + An example of creating an index with this operator class is: + +CREATE INDEX idxgin ON api USING gin (jdoc); + The non-default GIN operator class jsonb_hash_ops supports indexing the @> operator only. + An example of creating an index with this operator class is: + +CREATE INDEX idxginh ON api USING gin (jdoc jsonb_hash_ops); + + Consider the example of a table that stores JSON documents retrieved from a third-party web service, with a documented schema - definition. An example of a document retrieved from this web - service is as follows: + definition. A typical document is: { "guid": "9c36adc1-7fb5-4d5b-83b4-90356a46061a", @@ -305,85 +310,67 @@ CREATE INDEX idxginh ON api USING GIN (jdoc jsonb_hash_ops); ] } - If a GIN index is created on the table that stores these - documents, api, on its jdoc - jsonb column, we can expect that queries like the - following may make use of the index: + We store these documents in a table named api, + in a jsonb column named jdoc. + If a GIN index is created on this column, + queries like the following can make use of the index: -- Note that both key and value have been specified -SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @> '{"company": "Magnafone"}'; +SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @> '{"company": "Magnafone"}'; However, the index could not be used for queries like the - following, due to the aforementioned nesting restriction: + following, because though the operator ? is indexable, + it is not applied directly to the indexed column jdoc: -SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc -> 'tags' ? 'qui'; +SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc -> 'tags' ? 'qui'; - Still, with judicious use of expressional indexing, the above + Still, with judicious use of expression indexes, the above query can use an index scan. If there is a requirement to find those records with a particular tag quickly, and the tags have a high cardinality across all documents, defining an index as follows is an effective approach to indexing: --- Note that the "jsonb -> text" operator can only be called on an --- object, so as a consequence of creating this index the root "jdoc" --- datum must be an object. This is enforced during insertion. -CREATE INDEX idxgin ON api USING GIN ((jdoc -> 'tags')); +-- Note that the "jsonb -> text" operator can only be called on an +-- object, so as a consequence of creating this index the root of each +-- "jdoc" value must be an object. This is enforced during insertion. +CREATE INDEX idxgintags ON api USING gin ((jdoc -> 'tags')); + Now, the WHERE clause jdoc -> 'tags' ? 'qui' + will be recognized as an application of the indexable + operator ? to the indexed + expression jdoc -> 'tags'. + (More information on expression indexes can be found in .) - Expressional indexes are discussed in . - - - For the most flexible approach in terms of what may be indexed, - sophisticated querying on nested structures is possible by - exploiting containment. At the cost of having to create an index - on the entire structure for each row, and not just a nested - subset, we may exploit containment semantics to get an equivalent - result with a non-expressional index on the entire jdoc - column, without ever having to create additional - expressional indexes against the document (provided only - containment will be tested). While the index will be considerably - larger than our expression index, it will also be much more - flexible, allowing arbitrary structured searching. Such an index - can generally be expected to help with a query like the following: - + Another approach to querying is to exploit containment, for example: -SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @> '{"tags": ["qui"]}'; +SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @> '{"tags": ["qui"]}'; - - For full details of the semantics that these indexable operators - implement, see , . + This approach uses a single GIN index covering everything in the + jdoc column, whereas our expression index stored only + data found under the tags key. While the single-index + approach is certainly more flexible, targeted expression indexes + are likely to be smaller and faster to search than a single index. - - - <type>jsonb</> non-default GIN operator class - - jsonb - indexes on - + - Although only the @> operator is made indexable, a - jsonb_hash_ops operator class GIN index has - some notable advantages over an equivalent GIN index of the - default GIN operator class for jsonb. Search - operations typically perform considerably better, and the on-disk - size of a jsonb_hash_ops operator class GIN - index can be much smaller. + Although the jsonb_hash_ops operator class supports + only queries with the @> operator, it has notable + performance advantages over the default operator + class jsonb_ops. A jsonb_hash_ops + GIN index is usually much smaller than a jsonb_ops + index over the same data, and the specificity of searches is better, + particularly when queries contain tags that appear frequently in the + data. Therefore search operations typically perform considerably better + than with the default operator class. - - - <type>jsonb</> B-Tree and hash indexing + - jsonb comparisons and related operations are - type-wise, in that the underlying - PostgreSQL datatype comparators are - invoked recursively, much like a traditional composite type. - - - jsonb also supports btree and hash - indexes. Ordering between jsonb datums is: + jsonb also supports btree and hash + indexes. These are usually useful only if it's important to check + equality of complete JSON documents. + The btree ordering for jsonb datums is: Object > Array > Boolean > Number > String > Null @@ -391,23 +378,24 @@ SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @> '{"tags": ["qui"]}'; Array with n elements > array with n - 1 elements - Subsequently, individual primitive type comparators are invoked. - All comparisons of JSON primitive types occurs using the same - comparison rules as the underlying - PostgreSQL types. Strings are - compared lexically, using the default database collation. - Objects with equal numbers of pairs are compared: + Objects with equal numbers of pairs are compared in the order: key-1, value-1, key-2 ... - Note however that object keys are compared in their storage order, and in particular, - since shorter keys are stored before longer keys, this can lead to results that might be - unintuitive, such as: - { "aa": 1, "c": 1} > {"b": 1, "d": 1} + Note however that object keys are compared in their storage order, and + in particular, since shorter keys are stored before longer keys, this + can lead to results that might be unintuitive, such as: + +{ "aa": 1, "c": 1} > {"b": 1, "d": 1} + Similarly, arrays with equal numbers of elements are compared: element-1, element-2 ... + Primitive JSON values are compared using the same + comparison rules as for the underlying + PostgreSQL data type. Strings are + compared using the default database collation. diff --git a/doc/src/sgml/release-9.3.sgml b/doc/src/sgml/release-9.3.sgml index b4053c62bc..64b1801f3c 100644 --- a/doc/src/sgml/release-9.3.sgml +++ b/doc/src/sgml/release-9.3.sgml @@ -3618,14 +3618,14 @@ ALTER EXTENSION hstore UPDATE; Allow JSON values to be converted into records + linkend="functions-json">converted into records (Andrew Dunstan) - Add functions to convert + Add functions to convert scalars, records, and hstore values to JSON (Andrew Dunstan)