Graph Guide

```scala mdoc:invisible import lspace._ import lspace.Implicits.Scheduler.global import lspace.Implicits.SyncGuide.guide import lspace.provider.mem.MemGraph import Label.D._ import lspace.util.SampleGraph

 
## What is a graph
A graph is a collection of nodes, unordered edges and values, these are all resources. 
Nodes can be labelled and nodes can have edges.
Edges have a source ('from') and a destination ('to') resource which can both be either a node, edge or value. 
The edge is always labeled with a key (property) and an edge can also be the source to other edges (statements on edges).
Values have a data-value and values can have edges.

* Graphs support Librarian-traversals
* Graphs can be merged (graph ++ graph)
* Graphs support transactions (graph.transaction -> new in-memory graph with 'commit' function)
* Graph support history (*never delete, only add an edge (@deletedon) to the edge .. to be tested*)

create a graph
 ```scala mdoc
 val graph: Graph = MemGraph("graph-doc")
 import scala.concurrent.duration._
 scala.concurrent.Await.ready(lspace.util.SampleGraph.loadSocial(graph).runToFuture, 5.seconds)
 val labels = SampleGraph.ontologies
 val keys = SampleGraph.properties

How to use

First steps:

import lspace._ //easy access to common object (types) //easy access to common object (types)
import lspace.Implicits.Scheduler.global //default scheduler (execution context) //default scheduler (execution context)
import lspace.Implicits.SyncGuide.guide //graph-engine

To create a graph (in-memory):

val graph = Graph("my-graph-url")
// graph: Graph = graph:my-graph-url

A graph always has a name, ideally this would be a url so it can be referenced.

Before continuing reading and learning, first load some sample-data:

lspace.util.SampleGraph.loadSocial(graph).runToFuture
// res0: monix.execution.CancelableFuture[{val places: AnyRef{val SanJosédeMaipo: AnyRef{val place: lspace.structure.Node; val id: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultString.C]; val name: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultString.C]; val geo: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultGeopoint.C]}; val CrystalSprings: AnyRef{val place: lspace.structure.Node; val id: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultString.C]; val name: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultString.C]; val geo: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultGeopoint.C]}; val Haridwar: AnyRef{val place: lspace.structure.Node; val id: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultString.C]; val name: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultString.C]; val geo: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultGeopoint.C]}; val Talca: AnyRef{val place: lspace.structure.Node; val id: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultString.C]; val name: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultString.C]; val geo: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultGeopoint.C]}};val persons: AnyRef{val Yoshio: AnyRef{val person: lspace.structure.Node; val id: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultString.C]; val name: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultString.C]; val birthdate: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultLocalDate.C]; val birthPlace: lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node]; val balance: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultDouble.C]; val rate: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultInt.C]; val address: lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node]}; val Levi: AnyRef{val person: lspace.structure.Node; val id: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultString.C]; val name: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultString.C]; val birthdate: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultLocalDate.C]; val birthPlace: lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node]; val balance: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultDouble.C]; val rate: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultInt.C]; val address: lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node]}; val Gray: AnyRef{val person: lspace.structure.Node; val id: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultString.C]; val name: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultString.C]; val birthdate: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultLocalDate.C]; val birthPlace: lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node]; val balance: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultDouble.C]; val rate: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultInt.C]; val address: lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node]}; val Kevin: AnyRef{val person: lspace.structure.Node; val id: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultString.C]; val name: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultString.C]; val birthdate: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultLocalDate.C]; val birthPlace: lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node]; val balance: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultDouble.C]; val rate: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultInt.C]; val address: lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node]}; val Stan: AnyRef{val person: lspace.structure.Node; val id: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultString.C]; val name: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultString.C]; val birthdate: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultLocalDate.C]; val birthPlace: lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node]; val balance: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultInt.C]; val rate: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultInt.C]; val address: lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node]}; val Garrison: AnyRef{val person: lspace.structure.Node; val id: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultString.C]; val name: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultString.C]; val birthdate: lspace.structure.Edge[lspace.structure.Node,lspace.structure.util.ClassTypeable.defaultLocalDate.C]; val birthPlace: lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node]; val address: lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node]}};val knows: AnyRef{val GarrissonKnownStan: (lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node], lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node]); val GarrissonKnownKevin: (lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node], lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node]); val KevinKnownStan: (lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node], lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node]); val KevinKnownGray: (lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node], lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node]); val GrayKnowsLevi: (lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node], lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node]); val LeviKnowsYoshio: (lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node], lspace.structure.Edge[lspace.structure.Node,lspace.structure.Node])}}] = Async(
//   Future(<not completed>),
//   monix.eval.internal.TaskConnection$Impl$$anon$1@63dabd9d
// )

Graphs have a some basis API’s which allows for reading from and writing to the graph.

Resource API’s

Graph-resources can all be retrieved by Iri (@id) or by Id. Values and edges do mostly not have an Iri (empty-string). There are API’s on each structure-level (resource, value, edge and node).

The main methods per section:

Resources API

hasIri

graph.resources.hasIri("graph-doc/place/123")
// res1: monix.reactive.Observable[Resource[Any]] = monix.reactive.internal.operators.ConcatMapObservable@6874ba85
graph.resources.hasIri("graph-doc/place/123", "graph-doc/person/123")
// res2: monix.reactive.Observable[Resource[Any]] = monix.reactive.internal.operators.ConcatMapObservable@59ad4351

hasId

graph.resources.hasId(1001L).id
// res3: monix.eval.Task[Option[Long]] = Map(
//   FlatMap(
//     Eval(
//       lspace.provider.mem.store.MemStore$$Lambda$9126/0x0000000802959840@61f5af7c
//     ),
//     lspace.structure.Resources$$Lambda$9127/0x000000080295a040@263f9bb8
//   ),
//   lspace.package$ResourceOptionTask$$Lambda$9128/0x000000080295b040@4052ff8b,
//   0
// )

upsert

graph.values.create("some-literal")
// res4: monix.eval.Task[Value[String]] = FlatMap(
//   Async(<function2>, false, false, true),
//   lspace.structure.Values$$Lambda$9138/0x0000000802969840@43c6ba66
// )
graph.values.create("some-literal") //should be equal because values are deduplicated
// res5: monix.eval.Task[Value[String]] = FlatMap(
//   Async(<function2>, false, false, true),
//   lspace.structure.Values$$Lambda$9138/0x0000000802969840@521f1bbf
// ) //should be equal because values are deduplicated
graph.values.create("some-literal2") //new value, hence new id
// res6: monix.eval.Task[Value[String]] = FlatMap(
//   Async(<function2>, false, false, true),
//   lspace.structure.Values$$Lambda$9138/0x0000000802969840@474547d
// )

count:

graph.resources.count()
// res7: monix.eval.Task[Long] = Map(
//   Async(<function2>, true, true, true),
//   lspace.structure.Resources$$Lambda$9155/0x000000080297b040@6ed0e272,
//   0
// )

Resource

A resource ..

Nodes API

Nodes can be:

Retrieved by Iri(s)/Uri(s):

graph.nodes.hasIri("graph-doc/place/123")
// res8: monix.reactive.Observable[Node] = monix.reactive.internal.operators.ConcatMapObservable@4b5ec35f
graph.nodes.hasIri("graph-doc/place/123", "graph-doc/person/123")
// res9: monix.reactive.Observable[Node] = monix.reactive.internal.operators.ConcatMapObservable@6f08c742

Retrieved by Id(s):

graph.nodes.hasId(1002L)
// res10: monix.eval.Task[Option[Node]] = Eval(
//   lspace.provider.mem.store.MemStore$$Lambda$9126/0x0000000802959840@5764996e
// )

Counted:

graph.nodes.count()
// res11: monix.eval.Task[Long] = Eval(
//   lspace.provider.mem.store.MemStore$$Lambda$9148/0x0000000802978040@74e4f1a4
// )

Node

A node ..

Edges API

Edges can be:

Counted:

graph.edges.count()
// res12: monix.eval.Task[Long] = Eval(
//   lspace.provider.mem.store.MemStore$$Lambda$9148/0x0000000802978040@7ba81502
// )

Edge

An edge ..

Values API

Counted:

graph.values.count()
// res13: monix.eval.Task[Long] = Eval(
//   lspace.provider.mem.store.MemStore$$Lambda$9148/0x0000000802978040@2d582c07
// )

Value

A value ..

History

A graph can have a history trait which means that resources are time aware and annotated with supporting “@createdon” and “@deletedon” tags.