Projected result set goals
To make it easier for browser applications to fetch denormalized copies of entities referenced by foreign key, we'd like to be able to do some compact request and receive rows of data like:
[
{
"a": { columns of S:T, ... },
"b": { columns of entity referenced by S:T:b, ... },
"c": { columns of entity referenced by S:T:c, ... }
},
...
]
i.e. each row has a nested object containing column values for the main entity and referenced entities, where the client can define the output names for each object using our normal output renaming syntax in the URI.
API design challenge
This needs to handle the general case for specifying what foreign key to follow for each projected sub-object, which unfortunately means a messy syntax like ( path cols )=( schema cols ) to unambiguously specify a complete foreign key link structure.
This also raises questions as to how general it should be. Does it support both outbound and inbound foreign keys? Multiple hops, i.e. for association tables?
Possible API notations
Let's assume we want to add new projection syntax to the /attribute/ API.
Define object projection operators for one link
This approach tries to simplify notation with the limitation that at most one link can be traversed in the projection:
obj( link ) produces null or a single object {...}
- error to use with inbound links? or choose one entity arbitrarily?
objs( link ) produces an array of zero or more objects [{...}, ...]
Link notations:
example using obj |
equivalent link within entity paths |
obj() |
N/A (resolves to path context) |
obj(col1,col2) |
... /(col1,col2)/ ... |
obj(S:T:col1,col2) |
... /(S:T:col1,col2)/ ... |
obj(Alias:col1,col2) |
... /(Alias:col1,col2)/ ... |
obj(Alias:col1,col2=S:T:col1,col2) |
... /(Alias:col1,col2)=(S:T:col1,col2)/ ... |
The obj operator could also be replaced with objs to get an array instead of single object with no other difference in syntax.
Define subquery operators for one or more links
These all resolve an entity relpath relative to the current path context. This means that they use the notation for entity paths, starting with a path link element which denotes a link relative to the path context, instead of starting with a bare table reference from the schema. They can contain any number of filters and additional link elements after the first link element. An empty entity relpath is allowed to project the path context itself.
@E( entity relpath ) behaves like the /entity/ API as a subquery rooted at the current path context. (E stands for entity.)
@A( entity relpath / projection ) behaves like the /attribute/ API as a subquery rooted at the current path context. (A stands for attribute.)
@G( entity relpath / group keys ; projection ) behaves like the /attributegroup/ API as a subquery rooted at the current path context. (G stands for group.)
@R( entity relpath / projection ) behaves like the /aggregate/ API as a subquery rooted at the current path context. (R stands for reduce.)
The @(...) or @E(...) projection could express the same things as the previously proposed obj proposal but without the syntactic short-hands that omit parentheses. These parentheses are necessary to disambiguate table references from link endpoints.
| example |
@E() |
@E((col1,col2)) |
@E((S:T:col1,col2)) |
@E((Alias:col1,col2)) |
@E((Alias:col1,col2)=(S:T:col1,col2)) |
@E(S:T) |
@E((col1,col2)/(col3)/(col1)) |
We could add variants like @E1(...) to request a single object instead of a variable length array?
What we gain is the flexibility to express complex path navigation, do aggregate reductions of related entities, and possibly even use the notation recursively to build more deeply structured object trees as results. (Of course, such generalization of the syntax also requires a lot more development work to add the feature.)
Projected result set goals
To make it easier for browser applications to fetch denormalized copies of entities referenced by foreign key, we'd like to be able to do some compact request and receive rows of data like:
i.e. each row has a nested object containing column values for the main entity and referenced entities, where the client can define the output names for each object using our normal output renaming syntax in the URI.
API design challenge
This needs to handle the general case for specifying what foreign key to follow for each projected sub-object, which unfortunately means a messy syntax like
(path cols)=(schema cols)to unambiguously specify a complete foreign key link structure.This also raises questions as to how general it should be. Does it support both outbound and inbound foreign keys? Multiple hops, i.e. for association tables?
Possible API notations
Let's assume we want to add new projection syntax to the
/attribute/API.Define object projection operators for one link
This approach tries to simplify notation with the limitation that at most one link can be traversed in the projection:
obj(link)producesnullor a single object{...}objs(link)produces an array of zero or more objects[{...}, ...]Link notations:
objobj()obj(col1,col2)/(col1,col2)/...obj(S:T:col1,col2)/(S:T:col1,col2)/...obj(Alias:col1,col2)/(Alias:col1,col2)/...obj(Alias:col1,col2=S:T:col1,col2)/(Alias:col1,col2)=(S:T:col1,col2)/...The
objoperator could also be replaced withobjsto get an array instead of single object with no other difference in syntax.Define subquery operators for one or more links
These all resolve an entity relpath relative to the current path context. This means that they use the notation for entity paths, starting with a path link element which denotes a link relative to the path context, instead of starting with a bare table reference from the schema. They can contain any number of filters and additional link elements after the first link element. An empty entity relpath is allowed to project the path context itself.
@E(entity relpath)behaves like the/entity/API as a subquery rooted at the current path context. (Estands forentity.)@A(entity relpath/projection)behaves like the/attribute/API as a subquery rooted at the current path context. (Astands forattribute.)@G(entity relpath/group keys;projection)behaves like the/attributegroup/API as a subquery rooted at the current path context. (Gstands forgroup.)@R(entity relpath/projection)behaves like the/aggregate/API as a subquery rooted at the current path context. (Rstands forreduce.)The
@(...)or@E(...)projection could express the same things as the previously proposedobjproposal but without the syntactic short-hands that omit parentheses. These parentheses are necessary to disambiguate table references from link endpoints.@E()@E((col1,col2))@E((S:T:col1,col2))@E((Alias:col1,col2))@E((Alias:col1,col2)=(S:T:col1,col2))@E(S:T)@E((col1,col2)/(col3)/(col1))We could add variants like
@E1(...)to request a single object instead of a variable length array?What we gain is the flexibility to express complex path navigation, do aggregate reductions of related entities, and possibly even use the notation recursively to build more deeply structured object trees as results. (Of course, such generalization of the syntax also requires a lot more development work to add the feature.)