24.7 Creating a View Over JSON Data Based on Data-Guide Information

Based on data-guide information, you can create a database view whose columns project particular scalar fields from a set of JSON documents.

You can choose the fields to project by editing a hierarchical or schema data guide or by specifying a SQL/JSON path expression and possibly a minimum frequency of field occurrence.

You can create multiple views based on the same JSON document set, projecting different fields. See Multiple Data Guides Per Document Set.

You can create a view by projecting JSON fields using SQL/JSON function json_table — see Creating a View Over JSON Data Using JSON_TABLE.

An alternative is to use PL/SQL procedure DBMS_JSON.create_view or DBMS_JSON.create_view_on_path, to create a view by projecting fields that you choose based on available data-guide information.

The data-guide information can come from either:

  • A hierarchical or schema data guide that includes the fields to project, and possibly a SQL/JSON path expression.

  • A data guide-enabled JSON search index, together with a SQL/JSON path expression, and possibly a minimum field frequency.

In the former case, use procedure create_view. You can edit a (hierarchical or schema) data guide to specify fields that you want included. In this case you do not need (and for a schema data guide you cannot use) a data guide-enabled search index,

In the latter case, use procedure create_view_on_path. In this case you need a data guide-enabled search index, but you do not need a data guide.

In either case, you can provide a SQL/JSON path expression, to specify a field to be expanded for the view. This is required for procedure create_view_on_path. To specify a path for procedure create_view, use optional parameter PATH. The path $ creates a view starting from the JSON document root.

For procedure create_view_on_path, you can also provide a minimum frequency of occurrence, using optional parameter FREQUENCY. The resulting view includes only JSON fields along the path whose frequency is greater than the specified frequency.

When you specify a path, all descendant fields under it are expanded. A view column is created for each scalar value in the resulting subtree. The fields in the document set that are projected include both:

  • All scalar fields present, at any level, in the data that is targeted by the path expression.

  • All scalar fields, anywhere in the document, that are not under an array.

The path argument you provide must be a simple SQL/JSON path expression (no filter expression), possibly with relaxation (implicit array wrapping and unwrapping), but with no array steps and no function step. See SQL/JSON Path Expression Syntax.

Regardless of whether you use procedure create_view or create_view_on_path, in addition to the JSON fields that are projected as columns, all non-JSON columns of the table are also columns of the view.

The data guide that serves as the basis for a given view definition is static; it does not necessarily faithfully continue to reflect the current data in the document set. The fields that are projected for the view are determined when the view is created.

In particular, if you use create_view_on_path (which requires a data guide-enabled search index) then what counts are the fields specified by the given path expression and that have at least the given frequency (default 0), based on the index data at the time of the view creation.

There is also PL/SQL function DBMS_JSON.get_view_sql, which does not create a view, but instead returns the SQL DDL code that would create a view. You can, for example, edit that DDL to create different views.

You can also optionally obtain only the SQL SELECT statement that the view-creation DDL would use. In this case, if more columns would be needed for the view than the maximum number allowed, then the SELECT statement would involve joins of multiple json_table expressions. (The maximum number of columns allowed in a table (default: 1000) is defined by initialization parameter MAX_COLUMNS. See MAX_COLUMNS in Oracle Database Reference.)

_________________________________________________________

See Also:

24.7.1 Creating a View Over JSON Data Based on a Hierarchical or Schema Data Guide

You can use a hierarchical or schema data guide to create a database view whose columns project specified JSON fields from your documents. The fields projected are those in the data guide. You can edit the data guide to include only the fields that you want to project.

You can obtain a hierarchical or schema data guide using SQL function json_dataguide with argument DBMS_JSON.FORMAT_HIERARCHICAL or DBMS_JSON.FORMAT_SCHEMA, respectively.

You can edit the data guide obtained to include only specific fields, change the length of given types, or rename fields. The resulting data guide specifies which fields of the JSON data to project as columns of the view.

Note:

When you use a schema data guide to create a view that includes a column for a given field, if that field has values of different scalar types in the document set then a column is used for each of those scalar types. The names of such multiple columns other than the first have _N appended to the field name (N = 1, 2,…).

For example, if field a has a number value in one document and a string value in another document, then two columns are used in the view, one of type NUMBER and the other of type VARCHAR2. One column is named A; the other is named A_1.

You use PL/SQL procedure DBMS_JSON.create_view to create the view.

Example 24-5 illustrates this using a data guide obtained using Oracle SQL function json_dataguide with argument DBMS_JSON.FORMAT_HIERARCHICAL.

If you create a view using the data guide obtained using json_dataguide then GeoJSON data in your documents is supported. In this case the view column corresponding to the GeoJSON data has SQL data type SDO_GEOMETRY. For that you pass constant DBMS_JSON.GEOJSON or DBMS_JSON.GEOJSON+DBMS_JSON.PRETTY as the third argument to function json_dataguide.

Note:

Function json_dataguide cannot detect GeoJSON data if field coordinates or field geometries precedes field type in a GeoJSON object.

For example, this GeoJSON data is detected as such:

{"type"        : "Point",
 "coordinates" : [ 23.807, 7.121 ]}

This GeoJSON data is not detected as such (it is handled as arbitrary JSON data).

{"coordinates" : [ 23.807, 7.121 ]
 "type"        : "Point"}

See Also:

Example 24-5 Creating a View Using a Hierarchical Data Guide Obtained With JSON_DATAGUIDE

This example creates a view that projects all of the fields present in the hierarchical data guide that is obtained by invoking SQL function json_dataguide on data of table j_purchaseorder. The second and third arguments passed to json_dataguide are used, respectively, to specify that the data guide is to be hierarchical and pretty-printed.

The view column names come from the values of field o:preferred_column_name of the data guide that you pass to DBMS_JSON.create_view. By default, the view columns are thus named the same as the projected fields.

Because the columns must be uniquely named in the view, you must ensure that the field names themselves are unique. Optional parameter RESOLVENAMECONFLICTS does this by default (value true), but if you specify it as false then the names are not guaranteed to be unique. In this case (false), an alternative is to edit the data guide returned by json_dataguide to make the value of o:preferred_column_name unique. If parameter RESOLVENAMECONFLICTS is false, then an error is raised by DBMS_JSON.create_view if the names for the columns are not unique.

Although this example does not do so, you can provide a column-name prefix using DBMS_JSON.create_view with parameter colNamePrefix. For example, to get the same effect as that provided when you use a data guide obtained from the information in a data guide-enabled JSON search index, you could specify parameter colNamePrefix as 'DATA$', that is, the JSON column name, DATA followed by $. See Example 24-8.

DECLARE
  dg CLOB;
  BEGIN
    SELECT json_dataguide(data,
                          FORMAT DBMS_JSON.FORMAT_HIERARCHICAL,
                          DBMS_JSON.PRETTY)
      INTO dg
      FROM j_purchaseorder
      WHERE extract(YEAR FROM date_loaded) = 2014;
    DBMS_JSON.create_view('MYVIEW',
                          'J_PURCHASEORDER',
                          'DATA',
                          dg);
  END;
/

DESCRIBE myview
 Name                 Null?    Type
 -------------------- -------- ---------------------------
 DATE_LOADED                   TIMESTAMP(6) WITH TIME ZONE
 ID                   NOT NULL RAW(16)
 User                          VARCHAR2(8)
 PONumber                      NUMBER
 UPCCode                       NUMBER
 UnitPrice                     NUMBER
 Description                   VARCHAR2(32)
 Quantity                      NUMBER
 ItemNumber                    NUMBER
 Reference                     VARCHAR2(16)
 Requestor                     VARCHAR2(16)
 CostCenter                    VARCHAR2(4)
 AllowPartialShipment          VARCHAR2(4)
 name                          VARCHAR2(16)
 Phone                         VARCHAR2(16)
 type                          VARCHAR2(8)
 number                        VARCHAR2(16)
 city                          VARCHAR2(32)
 state                         VARCHAR2(2)
 street                        VARCHAR2(32)
 country                       VARCHAR2(32)
 zipCode                       NUMBER
 Special Instructions          VARCHAR2(8)

Related Topics

24.7.2 Creating a View Over JSON Data Based on a Path Expression

You can use the information in a data guide-enabled JSON search index to create a database view whose columns project JSON fields from your documents. The fields projected are the scalar fields not under an array plus the scalar fields in the data targeted by a specified SQL/JSON path expression.

For example, if the path expression is $ then all scalar fields are projected, because the root (top) of the document is targeted. Example 24-6 illustrates this. If the path is $.LineItems.Part then only the scalar fields that are present (at any level) in the data targeted by $.LineItems.Part are projected (in addition to scalar fields elsewhere that are not under an array). Example 24-7 illustrates this.

If you gather statistics on your JSON document set then the data-guide information in a data guide-enabled JSON search index records the frequency of occurrence, across the document set, of each path to a field that is present in a document. When you create the view, you can specify that only the (scalar) fields with a given minimum frequency of occurrence (as a percentage) are to be projected as view columns. You do this by specifying a non-zero value for parameter FREQUENCY of procedure DBMS_JSON.create_view_on_path.

For example, if you specify the path as $ and the minimum frequency as 50 then all scalar fields (on any path, since $ targets the whole document) that occur in at least half (50%) of the documents are projected. Example 24-8 illustrates this.

The value of argument PATH is a simple SQL/JSON path expression (no filter expression), possibly with relaxation (implicit array wrapping and unwrapping), but with no array steps and no function step. See SQL/JSON Path Expression Syntax.

No frequency filtering is done in either of the following cases — targeted fields are projected regardless of their frequency of occurrence in the documents:
  • You never gather statistics information on your set of JSON documents. (No frequency information is included in the data guide-enabled JSON search index.)

  • The FREQUENCY argument of DBMS_JSON.create_view_on_path is zero (0).

Note:

When the FREQUENCY argument is non-zero, even if you have gathered statistics information on your document set, the index contains no statistical information for any documents added after the most recent gathering of statistics. This means that any fields added after that statistics gathering are ignored (not projected).

See Also:

Example 24-6 Creating a View That Projects All Scalar Fields

All scalar fields are represented in the view, because the specified path is $.

(Columns whose names are italic in the describe command output are those that have been renamed using PL/SQL procedure DBMS_JSON.rename_column. Underlined rows are missing from Example 24-8.)

EXEC DBMS_JSON.create_view_on_path('VIEW2',
                                   'J_PURCHASEORDER',
                                   'DATA',
                                   '$');

DESCRIBE view2;
 Name                              Null?    Type
 --------------------------------  -------- ------------------
 ID                                NOT NULL RAW(16)
 DATE_LOADED                       TIMESTAMP(6) WITH TIME ZONE
 DATA$User                         VARCHAR2(8)
 PONumber                          NUMBER
 DATA$Reference                    VARCHAR2(16)
 DATA$Requestor                    VARCHAR2(16)
 DATA$CostCenter                   VARCHAR2(4)
 DATA$AllowPartialShipment         VARCHAR2(4)
 DATA$name                         VARCHAR2(16)
 Phone                             VARCHAR2(16)
 DATA$city                         VARCHAR2(32)
 DATA$state                        VARCHAR2(2)
 DATA$street                       VARCHAR2(32)
 DATA$country                      VARCHAR2(32)
 DATA$zipCode                      NUMBER
 DATA$SpecialInstructions          VARCHAR2(8)
 DATA$UPCCode                      NUMBER
 DATA$UnitPrice                    NUMBER
 PartDescription                   VARCHAR2(32)
 DATA$Quantity                     NUMBER
 ItemNumber                        NUMBER
 PhoneType                         VARCHAR2(8)
 PhoneNumber                       VARCHAR2(16)

Example 24-7 Creating a View That Projects Scalar Fields Targeted By a Path Expression

Fields Itemnumber, PhoneType, and PhoneNumber are not represented in the view. The only fields that are projected are those scalar fields that are not under an array plus those that are present (at any level) in the data that is targeted by $.LineItems.Part (that is, the scalar fields whose paths start with $.LineItems.Part). (Columns whose names are italic in the describe command output are those that have been renamed using PL/SQL procedure DBMS_JSON.rename_column.)

SQL> EXEC DBMS_JSON.create_view_on_path('VIEW4',
                                        'J_PURCHASEORDER',
                                        'DATA',
                                        '$.LineItems.Part');


SQL> DESCRIBE view4;
 Name                             Null?    Type
 -------------------------------- -------- ------------------
 ID                               NOT NULL RAW(16)
 DATE_LOADED                      TIMESTAMP(6) WITH TIME ZONE
 DATA$User                        VARCHAR2(8)
 PONumber                         NUMBER
 DATA$Reference                   VARCHAR2(16)
 DATA$Requestor                   VARCHAR2(16)
 DATA$CostCenter                  VARCHAR2(4)
 DATA$AllowPartialShipment        VARCHAR2(4)
 DATA$name                        VARCHAR2(16)
 Phone                            VARCHAR2(16)
 DATA$city                        VARCHAR2(32)
 DATA$state                       VARCHAR2(2)
 DATA$street                      VARCHAR2(32)
 DATA$country                     VARCHAR2(32)
 DATA$zipCode                     NUMBER
 DATA$SpecialInstructions         VARCHAR2(8)
 DATA$UPCCode                     NUMBER
 DATA$UnitPrice                   NUMBER
 PartDescription                  VARCHAR2(32)

Example 24-8 Creating a View That Projects Scalar Fields Having a Given Frequency

All scalar fields that occur in all (100%) of the documents are represented in the view. Field AllowPartialShipment does not occur in all of the documents, so there is no column DATA$AllowPartialShipment in the view. Similarly for fields Phone, PhoneType, and PhoneNumber.

(Columns whose names are italic in the describe command output are those that have been renamed using PL/SQL procedure DBMS_JSON.rename_column.)

SQL> EXEC DBMS_JSON.create_view_on_path('VIEW3',
                                        'J_PURCHASEORDER',
                                        'DATA',
                                        '$',
                                        100);


SQL> DESCRIBE view3;
 Name                             Null?    Type
 -------------------------------- -------- ------------------
 ID                               NOT NULL RAW(16)
 DATE_LOADED                      TIMESTAMP(6) WITH TIME ZONE
 DATA$User                        VARCHAR2(8)
 PONumber                         NUMBER
 DATA$Reference                   VARCHAR2(16)
 DATA$Requestor                   VARCHAR2(16)
 DATA$CostCenter                  VARCHAR2(4)
 DATA$name                        VARCHAR2(16)
 DATA$city                        VARCHAR2(32)
 DATA$state                       VARCHAR2(2)
 DATA$street                      VARCHAR2(32)
 DATA$country                     VARCHAR2(32)
 DATA$zipCode                     NUMBER
 DATA$SpecialInstructions         VARCHAR2(8)
 DATA$UPCCode                     NUMBER
 DATA$UnitPrice                   NUMBER
 PartDescription                  VARCHAR2(32)
 DATA$Quantity                    NUMBER
 ItemNumber                       NUMBER