-
Notifications
You must be signed in to change notification settings - Fork 3
ERMrest Programmatic API Sketch
This outline focuses on the application-side APIs, e.g. those used by a data or model-consuming client application. It ignores internal APIs needed to help implement the behaviors.
Some idioms assumed in this sketch:
- Using nested object structures to group API behaviors rather than using longer method names.
- See the
entity
,attribute
, andattributegroup
sub-APIs on datapath.
- Using container-like objects at branching points in the object tree with common signatures.
- See
schemas
,tables
,columns
, etc. - Having
.by_position
and.by_name
member access mechanisms, etc. - Assuming idioms for checking length, iterating, etc. (Implied rather than sketched out.)
- Putting management methods on the object being managed.
- Having
.delete()
on the object itself - Having
.create()
on the container-like object where new members are being added.
- Assuming Python-like semantics for sets, lists, tuples. Might need to adapt for Javascript.
A server is bound to a URL, and session credentials are established. Catalogs can be managed or bound to then work in a particular dataset.
A table object from the schema exposes both model access features and basic data access for the single table on the server.
The Dataquery() constructor instantiates a logical data access object. Many such objects can be instantiated from the same catalog to manage different data access tasks concurrently.
- ermrestFactory
- .getServer(url) -> returns a new or cached instance of a server
- server = Server(url)
- .uri
- .catalogs.create( catalogParams ) -> catalog
- .catalogs.length() -> count
- .catalogs.names() -> sequence of id
- .catalogs.get( id ) -> catalog
- catalog
- .server
- .id
- .delete()
- .schemas.create( schemaParams ) -> schema
- .schemas.length() -> count
- .schemas.names() -> sequence of schemaName
- .schemas.get( schemaName ) -> schema
- .schemas.all()
- TODO: owner, ACLs?
- schema
- .catalog
- .name
- .displayname
- .ignore
- .delete()
- .tables.create( tableParams ) -> table
- .tables.length() -> count
- .tables.names() -> sequence of tableName
- .tables.get( tableName ) -> table
- .tables.all()
- .annotations.create( annotationParams ) -> annotation
- .annotations.length() -> count
- .annotations.names() -> sequence of uri
- .annotations.get( uri ) -> annotation
- .annotations.all()
- table
- .schema
- .name
- .displayname
- .ignore
- .delete()
- .columns.create ( columnParams ) -> column
- .columns.length() -> count
- .columns.names() -> sequence of columnName ordered by position
- .columns.get( columnName ) : column
- .columns.getByPosition( index ) -> column
- .columns.all()
- .keys.create( keyParams ) -> key
- .keys.length() -> count
- .keys.colsets() -> sequence of colset
- .keys.get( colset ) -> key
- .keys.all()
- .foreignkeys.create( fkeyParams ) -> foreignkeyref
- .foreignkeys.length() -> count
- .foreignkeys.colsets()
- .foreignkeys.mappings() -> sequence of mapping
- .foreignkeys.get( mapping ) -> foreignkeyref
- .foreignkeys.get( colset ) -> foreignkeyref
- .foreignkeys.all()
- .annotations.create( annotationParams ) -> annotation
- .annotations.length() -> count
- .annotations.names() -> sequence of uri
- .annotations.get( uri ) -> annotation
- .annotations.all()
- .entity.get( filter=null, limit=null, columns=null, sortby=null ) -> rowSet
- .entity.getBefore( filter=null, limit, columns=null, sortby=null, row ) -> rowSet
- .entity.getAfter( filter=null, limit, columns=null, sortby=null, row ) -> rowSet
- .entity.count( filter=null ) -> count
- .entity.delete( filter=null ) : void
- .entity.put( rowSet ) -> rowSet
- .entity.post( rowSet ) -> rowSet
- .attribute.get( projection, filter=null ) -> rowSet
- .attribute.delete( projection, filter=null ) : void
- .attributegroup.get( grouping, projection, filter=null ) -> rowSet
- .attributegroup.put( grouping, projection, rowSet ) -> rowSet
- rowSet
- .length()
- .before() -> rowSet
- .after() -> rowSet
- column
- .table
- .name
- .displayname
- .type
- .nullok
- .default
- .comment
- .ignore
- .memberOfKeys -> []
- .memberOfForeignKeys -> []
- .delete()
- .annotations.create( annotationParams ) -> annotation
- .annotations.length() -> count
- .annotations.names() -> sequence of uri
- .annotations.get( uri ) -> annotation
- .annotations.all()
- type
- .name
- .is_array : boolean
- .base_type
- key
- .table
- .colset
- .annotations.create( annotationParams ) -> annotation
- .annotations.length() -> count
- .annotations.names() -> sequence of uri
- .annotations.get( uri ) -> annotation
- .annotations.all()
- colset: is a mathematical set of columns, i.e. all colsets containing the same N columns are equivalent
- .length() -> count
- .columns -> sequence of columns
- mapping: is a mathematical functional map, i.e. a mathematical set of (from -> to) column pairings
- .length() -> count
- .domain() -> sequence of fromColumn
- .get( fromColumn ) -> toColumn
- foreignkeyref
- .colset : colset of referencing columns
- .key : key being referenced
- .mapping
- .ignore
- .delete()
- .simple()
- .getDomainValues( limit=null ) -> rowset from the referenced key's table
- .annotations.create( annotationParams ) -> annotation
- .annotations.length() -> count
- .annotations.names() -> sequence of uri
- .annotation.get( uri ) -> annotation
- .annotation.all()
- annotation
- .subject : schema|table|column|key|foreignkeyref
- .uri
- .content
- .delete()
The objects above are relatively static, corresponding to server,
database, and model resources. The table
objects include basic data
access methods already outlined above and operate on one server-side
table at a time.
The objects below are dynamic views/wrappers over the database. A
pathtable
is a table instance in a particular query while table
is
an element of the database schema. A pathcolumn
is a column from one
table instance, while a column
is an element of the database schema.
A datapath
represents a particular dataset in an ERMrest catalog. It
combines one or more pathtable
instances linked into a relational
join and denoting a particular entity context. The datapath.copy()
method creates a shallow copy of a datapath such that further
extension of either copy will happen independently while they share
the pathtable
instances and relationships they both held at the time
of copy. The datapath.filter()
method also produces a shallow copy
but introduces a new filter constraint on the returned copy.
- datapath = Datapath(table)
- .catalog
- .context : pathtable
- .copy() -> datapath shallow copy
- .filter( filter ) -> datapath shallow copy with filter
- .extend(table, context=null, link=null) -> pathtable
- .entity.get( filter=null ) -> rowSet
- .entity.delete( filter=null ) : void
- .attribute.get( projection, filter=null ) -> rowSet
- .attribute.delete( projection, filter=null ) : void
- .attributegroup.get( grouping, projection, filter=null ) -> rowSet
- .aggregate.get( projection, filter=null ) -> rowSet
- pathtable
- .datapath
- .table
- .alias
- .columns.length() -> count
- .columns.names() -> sequence of names ordered by position
- .columns.get( columnName ) -> pathcolumn
- .columns.getByPosition( index ) -> pathcolumn
- pathcolumn
- .pathtable
- .column
- .operators.length() -> count
- .operators.names() -> sequence of operatorName
- .operators.get( operatorName )( rvalue=null ) -> filter
- filter = Negation(filter)
- .filter
- .toUri()
- filter = Conjunction([ filter, ... ])
- .filters : list of filters
- .toUri()
- filter = Disjunction([ filter, ... ])
- .filters : list of filters
- .toUri()
- filter = UnaryPredicate(pathcolumn | column, operator)
- .column : pathcolumn | column
- .operator : operatorName
- .toUri()
- filter = BinaryPredicate(pathcolumn | column, operator, rvalue)
- .column : pathcolumn | column
- .operator : operatorName
- .rvalue : literal
- .toUri()
This is a variant or wrapper for datapath that discovers facets automatically and handles the linkage of facet source tables to the main context table rather than the client building up the path structure.
- facetpath = Facetpath(table)
- .catalog
- .context : pathtable
- .facets.length() -> count
- .facets.names() -> sequence of facetName
- .facets.get( facetName ) : pathcolumn
- .facets.getByPosition( index ) : pathcolumn
- .entity.get() -> rowSet
- .attribute( projection ).get() -> rowSet
- .attributegroup( grouping )( projection ).get() -> rowSet
- .aggregate( projection ).get() -> rowSet
- filterpath
- .datapath
- .filter
- .entity.get() -> rowSet
- .entity.delete() : void
- .attribute( projection ).get() -> rowSet
- .attribute( projection ).delete() : void
- .attributegroup( group )( projection ).get() -> rowSet
- .aggregate( projection ).get() -> rowSet