A recent forum post inspired this brief article on generating summary data in JSON Relational Duality Views.
Typically you map a table’s columns to fields in the resulting JSON. If you can’t use a 1:1 mapping in your Duality View for any reason, it is possible to augment the Duality View with generated fields.
Let’s walk through an example using the Human Resources sample schema.
Default JSON Relational Duality View
What if you were required to provide a JSON Relational Duality View showing your company’s departments along with each department’s employees. In that case you could start like so:
create or replace force editionable json relational duality view hr.emp_dept_dv as hr.departments { _id : department_id departmentName : department_name employees : hr.employees @link (to : [department_id]) { employeeid : employee_id firstname : first_name lastname : last_name email : email }};
So far, no aggregate/summary detail is present. The Duality View returns each department, along with the employees. Here is the output for department number 20
select json_serialize(d.data pretty) datafrom emp_dept_dv dwhere d.data."_id" = 20;DATA___________________________________________________{ "_id": 20, "departmentName": "Marketing", "employees": [ { "employeeId": 201, "firstName": "Michael", "lastName": "Martinez", "email": "MMARTINE" }, { "employeeId": 202, "firstName": "Pat", "lastName": "Davis", "email": "PDAVIS" } ], "_metadata": { "etag": "032AB4D0D94BCEF16ED5244B95C19901", "asof": "00000000002D42FB" }}
So far, so good.
Adding summary information
Let’s assume the task is expanded to include the employees’ salaries, the number of employees by department, and the average salary of the department’s employees.
As per the documentation you can add fields to the JSON, and either calculate their values using SQL or a JSON Path Expression. Since the Duality View was initially defined using the GraphQL-like format, a JSON Path Expression has been chosen.
create or replace force editionable json relational duality view hr.emp_dept_dv as hr.departments @nocheck { _id : department_id departmentName : department_name employeeCount @generated (path : "@.employees.size()") avgSalary @generated (path : "@.employees.salary.avg()") employees : hr.employees @link (to : [department_id]) { employeeId : employee_id firstName : first_name lastName : last_name email : email salary }};
First, add the salary field to the employees array. You can see the new field in line 13. Next, focus on summary details: lines 5 and 6 add fields for employee count and average salary. The @generated annotation lets you define a JSON path and use item methods like size() and avg() to calculate these values.
Let’s have a look at the output:
select json_serialize(d.data pretty) datafrom emp_dept_dv dwhere d.data."_id" = 20;DATA___________________________________________________{ "_id" : 20, "_metadata" : { "etag" : "3091B9948A2D43A782E1BD90FCCBB872", "asof" : "000000000030007E" }, "departmentName" : "Marketing", "employees" : [ { "employeeId" : 201, "firstName" : "Michael", "lastName" : "Martinez", "email" : "MMARTINE", "salary" : 13000 }, { "employeeId" : 202, "firstName" : "Pat", "lastName" : "Davis", "email" : "PDAVIS", "salary" : 6000 } ], "employeeCount" : 2, "avgSalary" : 9500}
The augmented Duality View now displays the number of employees in department 20, as well as the average salary for the entire department, too.
Summary
You can enhance JSON Relational Duality Views by adding generated fields with SQL or JSON Path Expressions. Letting the database handle these calculations often boosts performance and relieves you from having to reinvent the wheel in the application tier.