DEV Community

Hartmut B.
Hartmut B.

Posted on

ActiveOrient: Universal Store Facility

In Part 3 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.

> Person.last.rid   => "34:0"
> "#34:0".expand.to_human 
 => "<Person[34:0] (...) >"
Enter fullscreen mode Exit fullscreen mode

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. It creates the grid and defines a method to_tg for String and Date/Time,

> Date.today.to_tg.datum
 => Fri, 02 Aug 2019 
 #  and 
"4.6.2015".to_tg
 => #<TG::Tag:0x00000000043c8c60 (...)
Enter fullscreen mode Exit fullscreen mode

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 and assign Seema's birthday. We use a specialized edge-class HAS_BIRTHDAY

> E.create_class :has_birthday
> sema = Child.where( name: 'Seema').first
> "20.6.2010".to_tg.assign vertex: sema, via: HAS_BIRTHDAY
Enter fullscreen mode Exit fullscreen mode

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.

> 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]
Enter fullscreen mode Exit fullscreen mode

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.

> 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>"]] 
Enter fullscreen mode Exit fullscreen mode

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:

> start.vector( 30, function: :count ){ :out_has_birthday } 
 => 1
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)