DEV Community

Cover image for Data Relationships in Nucleoid
Can Mingir for Nucleoid

Posted on

Data Relationships in Nucleoid

Nucleoid is an open source (Apache 2.0), a runtime environment that provides logical integrity in declarative programming, and at the same time, it stores declarative statements so that it doesn’t require external database, in short it can be used as database.

Data Structure

Data structures are also defined in declarative syntax. Let's say name is a variable, and by program requirements, name must be:

  • less than 10 characters
  • first character is upper case
  • contains no underscore character

so, this can be 3 separate declarations:

if( name.length > 10 ) {
  throw "INVALID_SIZE"
}
Enter fullscreen mode Exit fullscreen mode
if( ! /[A-Z]/.test( name.charAt(0) )) {
  throw "INVALID_FIRST_CHARACTER"
}
Enter fullscreen mode Exit fullscreen mode
if( name.indexOf("_") > -1 ) {
  throw "INVALID_SPECIAL_CHARACTER"
}
Enter fullscreen mode Exit fullscreen mode

Relationships

Relationships of objects are defined similar to database's relationships, but it requires to define in declarative syntax.

One-to-One

One-to-one's defined as referring object's property to another object instance.

> class Driver {}
> class Vehicle {}

> driver1 = new Driver();
> vehicle1 = new Vehicle();
> driver1.vehicle = vehicle1;
Enter fullscreen mode Exit fullscreen mode

Bidirectional relationships requires additional declaration in order to keep both side synced, so not recommended unless absolutely required, associative entity may be used as alternative.

Still all the declarations are applicable to the property:

> Vehicle.type = "CAR"
> driver1.vehicle.type
"CAR"
Enter fullscreen mode Exit fullscreen mode

One-to-Many

One-to-Many is defined in three ways:

List as in One's side

It is a list created as property:

> class Customer {}
> class Order {}

> Customer.orders = [];

> customer1 = new Customer();
> order1 = new Order();
> customer1.orders.push(order1);
Enter fullscreen mode Exit fullscreen mode

Property as in Many's side

It is a property created, which refers to other instance:

> class Employee {}
> class Project {}

> employee1 = new Employee()
> project1 = new Project();
> project1.employee = employee1;
Enter fullscreen mode Exit fullscreen mode

Both of first 2 options are not bidirectional.

Associative Entity

In this case, both objects will be registered in associative object:

> class User {}
> class Company {}
> class Registration {}

> if ( Registrations.filter( r => r.user == User ).length > 1 ) {
    throw "USER_ALREADY_REGISTERED"
  }

> user1 = new User();
> company1 = new Company();

> registration1 = new Registration();
> registration1.company = company1;
> registration1.user = user1;
Enter fullscreen mode Exit fullscreen mode

Having a declaration of if ( Registrations.filter( r => r.user == User ).length > 1 ){ .. } adds One-to-Many constraint. In this case, registering user1 to another company throws "USER_ALREADY_REGISTERED":

> company2 = new Company();
> registration2 = new Registration();
> registration2.company = company2
> registration2.user = user1;
> "USER_ALREADY_REGISTERED"
Enter fullscreen mode Exit fullscreen mode

Many-to-Many

Many-to-Many is relatively straightforward as only possible with associative entity without carrying any additional constraint.

> class Passenger {}
> class Flight {}
> class Ticket {}

> passenger1 = new Passenger();
> flight1 = new Flight();

> ticket1 = new Ticket();
> ticket1.passenger = passenger1
> ticket1.flight = flight1;

> flight2 = new Flight();

> ticket2 = new Ticket();
> ticket2.passenger = passenger1
> ticket2.flight = flight2;
Enter fullscreen mode Exit fullscreen mode

Queries

Queries is done with functional programming.

The runtime stores each instance into its class list like driver1 = new Driver() will be part of Drivers.

One-to-One

> Drivers.filter( d=> d.state == "GA").filter( d => d.vehicle.year > 2010)
// Finds drivers in GA state with car younger than 2010
Enter fullscreen mode Exit fullscreen mode

One-to-Many

> Orders.filter( o => o.price > 100 && o.customer.id == 192)
// Finds orders with bigger than $100 prize of customer with id 192
Enter fullscreen mode Exit fullscreen mode

Other direction

> Customers.find( c=> c.id == 192).orders.filter( o=>o.price > 100)
Enter fullscreen mode Exit fullscreen mode

Many-to-Many

Tickets.filter( t => t.passenger.id == 6912 && t.flight.destination == "LA")
// Finds ticket of passenger with id 6912 for destination to FL
Enter fullscreen mode Exit fullscreen mode

Reference: https://nucleoid.org/tutorial/

Top comments (0)