ActiveOrient: Universal Store Facility
Tags: ruby, activeorient, orientdb, timegrid
Published: 2019-08-03 19:54:16

In [Part 3](https://dev.to/topofocus/activeorient-inheritance-edges-and-nodes-3d4f) we claimed »Inheritance and the flexibility of the graphical vertex & edge approach open sudden opportunities.« Let's prove it right away. 

## The power of RID
`OrientDB` is a »multi model database«, capable to act as a (SQL)RDMS-, a KeyStore- and a Graph-Database. The KeyStore-Design requires the presence of an universal Key, that's `RID`. 

Each record has a `RID`, each Object is fully identified through its `RID`. Simple, but powerfull.
```ruby
> Person.last.rid   => "34:0"
> "#34:0".expand.to_human 
 => "<Person[34:0] (...) >"
```
Data-items loaded from the database carry their class-id. `ActiveOrient` autoloads the object and assigns the corresponding ruby-class. Thus any method defined in the model is accessible, any attribute is present as well as any join and any connected edge is waiting to be discovered. 

## Time Grid
Think of a mesh of date-items, supporting  one central goal: Provide an even access-time to any Date of a given time-period, to any item connected to the grid. 

This Graph is realized

> Jahr -- [MONTH_OF] -- Monat --[DAY_OF]-- Tag --[TIME_OF]-- Stunde

The nodes are crosslinked via GRID_OF-edges and any point of the grid is easily accessed.

To use the time-grid, install the [OrientDB-Time-Graph-Gem](https://github.com/topofocus/orientdb_time_graph). It creates the grid and defines a method `to_tg` for `String` and `Date/Time`,  
```ruby
> Date.today.to_tg.datum
 => Fri, 02 Aug 2019 
 #  and 
"4.6.2015".to_tg
 => #<TG::Tag:0x00000000043c8c60 (...)
```
#### Store Items
By simply `assigning` a database-record to the `Tag`-Object, the universal store facility is created. 

Lets go back to our family of [Part 3](https://dev.to/topofocus/activeorient-inheritance-edges-and-nodes-3d4f) and assign `Seema's` birthday.  We use a specialized edge-class `HAS_BIRTHDAY`

```ruby 
> E.create_class :has_birthday
> sema = Child.where( name: 'Seema').first
> "20.6.2010".to_tg.assign vertex: sema, via: HAS_BIRTHDAY
```
#### Query

Let's consider two use-cases
* we just want to know Seemas birthday
* we are interested in all birthdays in June 2010

##### Seemas Birthday
We can simply get the Child-Record and follow the link to the time-grid.
```ruby
> sema = Child.where( name: 'Seema').first.to_human
"<Child[147:0]: in: {IS_CHILD=>1, HAS_BIRTHDAY=>1}, name : Seema>" 

> seema.nodes(:in, via: /birth/).datum  # firing a query 
 #or
> seema.in_has_birthday.out                # performs action in ruby
 => [Sun, 20 Jun 2010]
```
This is similar to an RDMS(SQL)-approach.

##### Any Birthday in a given range
Suppose, you got a huge database, full of birthdays and want to mine the data. In the RDMS-World you would query the hole database-table. The more data, to longer it takes. Even if you are just interested in People with Birthdays in the same month then Seema, there is no way to avoid accessing all birthday-records in store. 

The »Time-Graph« offers constant access time regardless of the size.
We just jump to one boundary of our range of interest and traverse the next 30 day-records. 

```ruby
> start = "1.6.2010".to_tg   
> start.vector( 30 ){ :out_has_birthday }
# INFO->select out_has_birthday from  ( traverse  outE('tg_grid_of').in  from #55:5042 while $depth < 30   )  where $depth >= 0 
 => ["#52:5043"] 
> start.vector( 30 ){ :out_has_birthday }.expand.nodes(via: /birth/).to_human
=> [["<TgChild[147:0]: in: {TG_IS_CHILD=>1, TG_HAS_BIRTHDAY=>1}, name : Seema>"]] 
```
The method »vector« encapsulates the traverse query. We follow 30 time-grid-links (30 days) and are looking for an property »out_has_birthday«. The query returns an array of `RID`'s  (of Time-Grid-Elements). We expand them manually and follow the link `HAS_BIRTHDAY`.

If we are interested in the count of birthday's in a specific range:
```ruby
> start.vector( 30, function: :count ){ :out_has_birthday } 
 => 1
```
### Conclusion
Database Design matters, even if a flexible multi-model-database is used. This simple pattern opens a door to »sustainable programming«. In contrast to classical RDMS(SQK)-Databases, using a Time-Grid, time-dependent data are stored in an unified environment. Queries are time-invariant. That means: if a database matures, grows and evolves, on can expect constant access times to its heart: the Time-Grid. The possibility of an assignment of any (seriable) ruby object to the time-grid is self evident.