Traversal Guide

Overview

To acquire knowledge, one must be able to communicate with the Librarian. This document should provide guidance in reasoning on a graph.

The traverser

When a librarian is sent on his way to gather knowledge as instructed with a traversal, the librarian (aka traverser) moves through L-space (aka graph(s)) and keeps track of his whereabouts and the encountered resources. When he reaches the end of the traversal he communicates back the result that was requested.

The traversal

A traversal is an ADT structure which can be compared, concatenated, serialized/deserialized etc. A traversal exists of steps which are grouped into segments (rules on segmentation: …). A segments starts with a move or transform step (new librarian with new information). To make a traversal ready for execution add .withGraph(graph) after the execution. This action will analyse the traversal, depending on the nature of the traversal, guide and the result-type the user can do one of the following monadic operations:

  • .headF
  • .headOptionF
  • .lastF
  • .lastOptionF
  • .toListF
  • .toSetF
  • .toMapF this one is only available when there is a Group-step at the root of all container-typed steps

when synchronous operations are available each of these methods has a synchronous counterpart without the ‘F’-suffix

Steps

The librarian is able to execute the following steps.

Resource steps

Resource-step to start specify what type of resources the traversal should start in.

Graph

Graph-selection step to point the librarian to a specific part of the L-space (we would not want to defy the large quantity of knowledge from the whole multiverse has to offer).

val graph: Graph = MemGraph("librarian-doc")
// graph: lspace.structure.Graph = graph:librarian-doc

import scala.concurrent.duration._
// import scala.concurrent.duration._

scala.concurrent.Await.ready(lspace.util.SampleGraph.loadSocial(graph).runToFuture, 5.seconds)
// res0: monix.execution.CancelableFuture[AnyRef{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.ut...

val labels = SampleGraph.ontologies
// labels: lspace.util.SampleGraph.ontologies.type = lspace.util.SampleGraph$ontologies$@7c56c89d

val keys = SampleGraph.properties
// keys: lspace.util.SampleGraph.properties.type = lspace.util.SampleGraph$properties$@4daf9672

N

N-step is a node selection step

E

E-step is an edge selection step

V

V-step is a value selection step

R

R-step is a resource (node, edge and value) selection step

Filter steps

A filter determines if the traverser should continue with the traversal or not.

Has steps

Has

Has-step validates the presence of a property and optionally asserts it by one or more predicates

g.N.has("name").out("name").withGraph(graph).toList //filters on nodes which have an edge with property "name"
// res1: List[Any] = List(Stan, Crystal Springs, Yoshio, Garrison, Gray, Haridwar, San José de Maipo, Kevin, Levi, Talca)

g.N.has("name", P.eqv("Garrison")).out("name").withGraph(graph).toList //adds an equality constraint with value "Alice"
// res2: List[Any] = List(Garrison)

g.N.has(keys.birthDate, P.gt(LocalDate.parse("2002-06-13"))).id.withGraph(graph).toList
// res3: List[Long] = List(1203, 1142)
HasNot

HasNot-step is the inverse of a Has-step (this could also be written as .not(_.has(..)))

HasLabel

HasLabel-step validates the precence of one or more labels (ontology, property or datatype)

g.N.hasLabel(labels.person).out(keys.name).withGraph(graph).toList //filters all persons
// res4: List[Any] = List(Stan, Yoshio, Garrison, Gray, Kevin, Levi)

g.N.hasLabel(labels.place).out(keys.name).withGraph(graph).toList //filters all places
// res5: List[Any] = List(Crystal Springs, Haridwar, San José de Maipo, Talca)
HasId

HasId-step validates if the id is within a certain set.

g.N.hasId(1001l).out(keys.name).withGraph(graph).toList
// res6: List[Any] = List(San José de Maipo)
HasIri

HasIri-step validates if the iri is within a certain set.

g.N.hasIri("graph-doc/place/123").out(keys.name).withGraph(graph).toList
// res7: List[Any] = List()

Global Filter steps

Dedup

Dedup-step filters traversers with distinct values

g.N.limit(1).union(_.out().limit(1), _.out().limit(1)).count.withGraph(graph).head //shouldBe 2
// res8: Long = 2

g.N.limit(1).union(_.out().limit(1), _.out().limit(1)).dedup().count.withGraph(graph).head //shouldBe 1
// res9: Long = 1

Coin

Coin-step filters traversers on a coin-flip result for probability p

g.N.count.withGraph(graph).head //total nodes to draw from
// res10: Long = 10

g.N.coin(0.2).id.withGraph(graph).toList //random selection of nodes with p = 0.2 (20%)
// res11: List[Long] = List()

g.N.coin(0.8).id.withGraph(graph).toList //random selection of nodes with p = 0.8 (80%)
// res12: List[Long] = List(1218, 1028, 1092, 1229, 1064, 1203, 1142, 1085)

Where

Where-step takes a traversal and filters on non-empty results

g.N.where(_.has("name")).out("name").withGraph(graph).toList
// res13: List[Any] = List(Stan, Crystal Springs, Yoshio, Garrison, Gray, Haridwar, San José de Maipo, Kevin, Levi, Talca)

And

And-step takes one or more traversals and filters only those which have non-empty results for all traversals

g.N.and(_.has("name"), _.has("https://example.org/birthDate")).out(keys.name, keys.birthDate).withGraph(graph).toList
// res14: List[Any] = List(Stan, 2002-06-13, Yoshio, 1996-08-18, Garrison, 1994-06-18, Gray, 1997-04-10, Kevin, 2008-11-30, Levi, 2008-12-20)

g.N.and(_.has(keys.balance, P.gt(300)), _.has(keys.balance, P.lt(3000))).count.withGraph(graph).head //shouldBe 2
// res15: Long = 2

Or

Or-step takes one or more traversals and filters only those which have non-empty results for at least one traversal

g.N.or(_.has("name"), _.has("https://example.org/birthDate")).out(keys.name, keys.birthDate).withGraph(graph).toList
// res16: List[Any] = List(Stan, 2002-06-13, Crystal Springs, Yoshio, 1996-08-18, Garrison, 1994-06-18, Gray, 1997-04-10, Haridwar, San José de Maipo, Kevin, 2008-11-30, Levi, 2008-12-20, Talca)

Not

Not-step takes a traversal and filters on empty results

g.N.not(_.has("name")).limit(2).id.withGraph(graph).toList
// res17: List[Long] = List()

Is

Is-step asserts a value against one or more predicates

g.N.out().is(P.eqv(300)).out(keys.name).withGraph(graph).toList //filters the all outgoing resources with value 2
// res18: List[Any] = List()

Clip steps

A clip step cuts the resulting stream of traversers.

Range

Range-step filters by a low-end and high-end index

g.N.range(4, 16).iri.withGraph(graph).toList //takes only node 4 until 16
// res19: List[String] = List(librarian-doc/person/56789, librarian-doc/person/345, librarian-doc/place/345, librarian-doc/place/123, librarian-doc/person/34567, librarian-doc/person/12345, librarian-doc/place/34567)

Limit

Limit-step takes the first x-number of traversers

g.N.limit(12).iri.withGraph(graph).toList //takes only the first 12 nodes
// res20: List[String] = List(librarian-doc/person/567, librarian-doc/place/12345, librarian-doc/person/123, librarian-doc/person/56789, librarian-doc/person/345, librarian-doc/place/345, librarian-doc/place/123, librarian-doc/person/34567, librarian-doc/person/12345, librarian-doc/place/34567)

Skip

Skip-step ignores the first x-number of traversers

g.N.skip(12).iri.withGraph(graph).toList //ignores the first 12 nodes
// res21: List[String] = List()

Tail

Tail-step takes the last x-number of traversers

g.N.tail(12).iri.withGraph(graph).toList //takes only the last 12 nodes
// res22: List[String] = List(librarian-doc/person/567, librarian-doc/place/12345, librarian-doc/person/123, librarian-doc/person/56789, librarian-doc/person/345, librarian-doc/place/345, librarian-doc/place/123, librarian-doc/person/34567, librarian-doc/person/12345, librarian-doc/place/34567)

Move steps

Move steps lets the traverser move through the graph. The path can be stored within the traverer

Out

Out-step takes one or more property-labels and traverses along the valid outgoing paths if any

g.N.out("name").withGraph(graph).toList
// res23: List[Any] = List(Stan, Crystal Springs, Yoshio, Garrison, Gray, Haridwar, San José de Maipo, Kevin, Levi, Talca)

OutE

OutE-step takes one or more property-labels and traverses to the valid outgoing paths if any

g.N.outE("name").withGraph(graph).toList
// res24: List[lspace.structure.Edge[lspace.structure.Node,Any]] = List(lspace.provider.mem.MemGraph$$anon$8@5db0e4c9, lspace.provider.mem.MemGraph$$anon$8@5db0e421, lspace.provider.mem.MemGraph$$anon$8@5db0e456, lspace.provider.mem.MemGraph$$anon$8@5db0e4d4, lspace.provider.mem.MemGraph$$anon$8@5db0e4a9, lspace.provider.mem.MemGraph$$anon$8@5db0e433, lspace.provider.mem.MemGraph$$anon$8@5db0e3f5, lspace.provider.mem.MemGraph$$anon$8@5db0e4be, lspace.provider.mem.MemGraph$$anon$8@5db0e495, lspace.provider.mem.MemGraph$$anon$8@5db0e444)

In

In-step takes one or more property-labels and traverses along the valid incoming paths if any

g.N.out("name").withGraph(graph).toList
// res25: List[Any] = List(Stan, Crystal Springs, Yoshio, Garrison, Gray, Haridwar, San José de Maipo, Kevin, Levi, Talca)

InE

InE-step takes one or more property-labels and traverses to the valid incoming paths if any

g.N.outE("name").withGraph(graph).toList
// res26: List[lspace.structure.Edge[lspace.structure.Node,Any]] = List(lspace.provider.mem.MemGraph$$anon$8@5db0e4c9, lspace.provider.mem.MemGraph$$anon$8@5db0e421, lspace.provider.mem.MemGraph$$anon$8@5db0e456, lspace.provider.mem.MemGraph$$anon$8@5db0e4d4, lspace.provider.mem.MemGraph$$anon$8@5db0e4a9, lspace.provider.mem.MemGraph$$anon$8@5db0e433, lspace.provider.mem.MemGraph$$anon$8@5db0e3f5, lspace.provider.mem.MemGraph$$anon$8@5db0e4be, lspace.provider.mem.MemGraph$$anon$8@5db0e495, lspace.provider.mem.MemGraph$$anon$8@5db0e444)

Label

Label-step traverses to the label-nodes if any

g.N.label().withGraph(graph).toList
// res27: List[lspace.structure.Ontology] = List(ontology:https://example.org/Person, ontology:https://example.org/Place, ontology:https://example.org/Person, ontology:https://example.org/Person, ontology:https://example.org/Person, ontology:https://example.org/Place, ontology:https://example.org/Place, ontology:https://example.org/Person, ontology:https://example.org/Person, ontology:https://example.org/Place)

Branche steps

Branche steps can execute one or more separate traversals, execute those in a specific way and merges any results back into the original traversal

Union

Union-step takes one or more traversals and merges the results into a single traversal

g.N.union(_.out(), _.in()).withGraph(graph).toList //all incoming and outgoing edges
// res28: List[Any] = List(2002-06-13, 300, 4, librarian-doc/person/567, lspace.provider.mem.MemGraph$$anon$7@5db0e4d0, lspace.provider.mem.MemGraph$$anon$7@5db0e4b6, Stan, lspace.provider.mem.MemGraph$$anon$7@5db0e3ec, lspace.provider.mem.MemGraph$$anon$7@5db0e4d0, lspace.provider.mem.MemGraph$$anon$7@5db0e4b6, librarian-doc/place/12345, Point(-48.4046,175.87173), Crystal Springs, lspace.provider.mem.MemGraph$$anon$7@5db0e479, lspace.provider.mem.MemGraph$$anon$7@5db0e447, 1996-08-18, 10.34, 4, librarian-doc/person/123, lspace.provider.mem.MemGraph$$anon$7@5db0e479, Yoshio, lspace.provider.mem.MemGraph$$anon$7@5db0e407, lspace.provider.mem.MemGraph$$anon$7@5db0e479, 1994-06-18, librarian-doc/person/56789, lspace.provider.mem.MemGraph$$anon$7@5db0e4b6, lspace.provider.mem.MemGraph$$anon$7@...

g.N.union(_.has(keys.balance, P.gt(300)), _.has(keys.balance, P.lt(-200))).count.withGraph(graph).head //should be 3
// res29: Long = 3

Local

Local-step takes a traversal and performs any barrier, environment or other more global operations only over the results upto the traverser at the root the local-traversal

g.N.local(_.out().hasLabel[Int].sum).withGraph(graph).toList //sums all outgoing edges to integers for each node in the graph
// res30: List[Double] = List(304.0, 0.0, 4.0, 0.0, 1.0, 0.0, 0.0, 2.0, 2.0, 0.0)

Repeat

Repeat-step takes a traversal and keeps repeating it until a certain requirement is met, a maximum number of repeats is reached or the traversal is exhausted. A repeat step returns only the result of the last repeat iteration but can also return the result of each intermediary iteration by providing ‘collect = true’.

g.N.repeat(_.out("knows")).withGraph(graph).toList //repeats as long as there are outgoing "knows" edges (can easily contain infinite loops)
// res31: List[Any] = List()

g.N.repeat(_.out("knows"))(_.hasLabel(Ontology("Officer"))).withGraph(graph).toList //repeats as long as there are outgoing "knows" edges and the result is not of type "Officer"
// res32: List[Any] = List()

g.N.repeat(_.out("knows"), 3)(_.hasLabel(Ontology("Officer"))).withGraph(graph).toList //repeats three times at most if there are outgoing "knows" edges and the result is not of type "Officer"
// res33: List[Any] = List()

g.N.repeat(_.out("knows"), 3, true)(_.hasLabel(Ontology("Officer"))).withGraph(graph).toList //repeats three times at most if there are outgoing "knows" edges and the result is not of type "Officer" and returns every result in between
// res34: List[Any] = List()

g.N.repeat(_.out("knows"), collect = true)(_.hasLabel(Ontology("Officer"))).withGraph(graph).toList //repeats as long as there are outgoing "knows" edges and the result is not of type "Officer" and returns every result in between
// res35: List[Any] = List()

g.N.repeat(_.out("knows"), max = 3).withGraph(graph).toList //repeats three times at most if there are outgoing "knows" edges
// res36: List[Any] = List()

g.N.repeat(_.out("knows"), max = 3, collect = true).withGraph(graph).toList //repeats three times at most if there are outgoing "knows" edges and returns every result in between
// res37: List[Any] = List()

Coalesce

Coalesce-step takes one or more traversals and returns the result of the first non-empty traversal

g.N.coalesce(_.has(keys.rate, P.gte(4)).iri, _.has(keys.balance, P.lt(-200)).iri).withGraph(graph).head
// res38: String = librarian-doc/person/567

Choose

Choose-step takes a right or left traversal, right if the by-traversal is non-empty, left if it is empty.

g.N.choose(_.has(keys.rate, P.gte(4)), _.constant(true), _.constant(false)).withGraph(graph).toList 
// res39: List[Boolean] = List(true, false, true, false, false, false, false, false, false, false)

g.N.hasIri(graph.iri + "/place/123").choose(_.count.is(P.eqv(1)), _.constant(true), _.constant(false)).withGraph(graph).head
// res40: Boolean = true

Map steps

Map steps …

OutMap

OutMap-step groups the resultset into a Map[Property,List[Value]] where OutMap is the edge label by which it is grouped and List[Value] is the list of values for a certain Property. If the traversal has any succeeding steps after the OutMap-step, the traversal will continue to operate with a traverser for each Value.

g.N.outMap() //returns a property-map on all out-going connected resources
// res41: lspace.librarian.traversal.Traversal[lspace.structure.ClassType[Any],lspace.datatype.MapType[Map[lspace.structure.Property,List[Any]]],lspace.librarian.traversal.step.OutMap :: lspace.librarian.traversal.step.N :: shapeless.HNil] = Traversal(OutMap(Set()) :: N(List()) :: HNil)

g.N.has("name", P.eqv("Garrison")).outMap().withGraph(graph).head
// res42: scala.collection.immutable.Map[lspace.structure.Property,List[Any]] = Map(property:name -> List(Garrison), property:https://example.org/birthPlace -> List(lspace.provider.mem.MemGraph$$anon$7@5db0e440), property:https://example.org/birthDate -> List(1994-06-18), property:https://example.org/knows -> List(lspace.provider.mem.MemGraph$$anon$7@5db0e4b6, lspace.provider.mem.MemGraph$$anon$7@5db0e4c5), property:@id -> List(librarian-doc/person/56789))

g.N.outMap("name", "knows") //returns a property-map for edges with label "name" or "knows"
// res43: lspace.librarian.traversal.Traversal[lspace.structure.ClassType[Any],lspace.datatype.MapType[Map[lspace.structure.Property,List[Any]]],lspace.librarian.traversal.step.OutMap :: lspace.librarian.traversal.step.N :: shapeless.HNil] = Traversal(OutMap(Set(property:name, property:knows)) :: N(List()) :: HNil)
OutEMap
g.N.has("name", P.eqv("Garrison")).outEMap().withGraph(graph).head //should return all out-going edges grouped by key
// res44: scala.collection.immutable.Map[lspace.structure.Property,List[lspace.structure.Edge[lspace.structure.Node,Any]]] = Map(property:name -> List(lspace.provider.mem.MemGraph$$anon$8@5db0e4d4), property:https://example.org/birthPlace -> List(lspace.provider.mem.MemGraph$$anon$8@5db0e4d7), property:https://example.org/birthDate -> List(lspace.provider.mem.MemGraph$$anon$8@5db0e4d6), property:https://example.org/knows -> List(lspace.provider.mem.MemGraph$$anon$8@5db0e4dd, lspace.provider.mem.MemGraph$$anon$8@5db0e4d8), property:@id -> List(lspace.provider.mem.MemGraph$$anon$8@5db0e4d2))
InMap
g.N.has("name", P.eqv("Garrison")).inMap().withGraph(graph).head //returns a property-map on all incoming connected resources
// res45: scala.collection.immutable.Map[lspace.structure.Property,List[Any]] = Map(property:https://example.org/knows -> List(lspace.provider.mem.MemGraph$$anon$7@5db0e4c5, lspace.provider.mem.MemGraph$$anon$7@5db0e4b6))
InEMap
g.N.has("name", P.eqv("Garrison")).inEMap().withGraph(graph).head //should return all in-coming edges grouped by key
// res46: scala.collection.immutable.Map[lspace.structure.Property,List[lspace.structure.Edge[Any,lspace.structure.Node]]] = Map(property:https://example.org/knows -> List(lspace.provider.mem.MemGraph$$anon$8@5db0e4da, lspace.provider.mem.MemGraph$$anon$8@5db0e4df))

Traverse steps

Id

Id-step returns the resource-id (long)

g.N.id.withGraph(graph).toList
// res47: List[Long] = List(1218, 1028, 1092, 1229, 1186, 1064, 1001, 1203, 1142, 1085)

Constant

Constant-step returns a traverser with the provided constant-value

g.N.constant(42).withGraph(graph).head
// res48: Int = 42

From

From-step …

g.E.from.withGraph(graph).toList
// res49: List[Any] = List(lspace.provider.mem.MemGraph$$anon$7@5db0e479, lspace.provider.mem.MemGraph$$anon$7@5db0e3ec, lspace.provider.mem.MemGraph$$anon$7@5db0e479, lspace.provider.mem.MemGraph$$anon$7@5db0e479, lspace.provider.mem.MemGraph$$anon$7@5db0e479, lspace.provider.mem.MemGraph$$anon$7@5db0e407, lspace.provider.mem.MemGraph$$anon$7@5db0e407, lspace.provider.mem.MemGraph$$anon$7@5db0e479, lspace.provider.mem.MemGraph$$anon$7@5db0e479, lspace.provider.mem.MemGraph$$anon$7@5db0e4a5, lspace.provider.mem.MemGraph$$anon$7@5db0e407, lspace.provider.mem.MemGraph$$anon$7@5db0e4a5, lspace.provider.mem.MemGraph$$anon$7@5db0e4a5, lspace.provider.mem.MemGraph$$anon$7@5db0e4a5, lspace.provider.mem.MemGraph$$anon$7@5db0e42b, lspace.provider.mem.MemGraph$$anon$7@5db0e42b, lspace.provider.mem.M...

To

To-step …

g.E.to.withGraph(graph).toList
// res50: List[Any] = List(librarian-doc/person/12345, Point(72.0403,60.90879), Levi, 2008-12-20, lspace.provider.mem.MemGraph$$anon$7@5db0e407, librarian-doc/place/12345, Crystal Springs, -245.05, 2, librarian-doc/person/345, Point(-48.4046,175.87173), Gray, 1997-04-10, lspace.provider.mem.MemGraph$$anon$7@5db0e42b, librarian-doc/place/345, Haridwar, 2230.3, 1, librarian-doc/person/34567, Kevin, Point(89.45136,88.01204), 2008-11-30, lspace.provider.mem.MemGraph$$anon$7@5db0e3ec, librarian-doc/place/34567, 500.5, Talca, 2, Point(74.32746,-45.06438), librarian-doc/person/567, Stan, 2002-06-13, lspace.provider.mem.MemGraph$$anon$7@5db0e3ec, librarian-doc/person/123, 300, 4, librarian-doc/person/56789, Garrison, Yoshio, 1994-06-18, lspace.provider.mem.MemGraph$$anon$7@5db0e440, 1996-08-18, ls...

Barrier steps

Barrier steps can operate on the entire resultset of a traversal

Collecting barrier steps

Collecting steps …

Group

Group-step groups the resultset into a Map[Key,List[Value]] where Key is the value by which it is grouped and List[Value] is the list of values which have the same group-key. If the traversal has any succeeding steps after the Group-step, the traversal will continue to operate with a traverser for each Value.

g.N.group(_.out("name")).mapValues(_.iri).withGraph(graph).head //groups only on nodes with a "name" and only takes the first result (head)
// res51: (List[Any], List[String]) = (List(Garrison),List(librarian-doc/person/56789))

g.N.group(_.out("name")).mapValues(_.group(_.out("age")).mapValues(_.iri)).withGraph(graph).head //can e.g. be a Map[String, List[Map[Int,List[Node]]]]
// res52: (List[Any], scala.collection.immutable.Map[List[Any],List[String]]) = (List(Garrison),Map(List() -> List(librarian-doc/person/56789)))

Reducing barrier steps

Reducing barrier steps perform a fold task on all traverers in the stream resulting in a single traverser with the resulting value of the fold task.

Mean

Mean-step passes a traverser where the value is the mean of the values of incoming traversers

g.N.out("balance").hasLabel(`@double`).mean.withGraph(graph).head //should be 624.0225
// res53: Double = 624.0225
Sum

Sum-step passes a traverser where the value is the sum of the values of incoming traversers

g.N.out("balance").hasLabel(`@double`).sum.withGraph(graph).head //should be 2496.09
// res54: Double = 2496.09

Filter barrier steps

Filter barrier steps filters traversers based on some comparison against the complete stream of traversers.

Min

Min-step passes only the traverser with the smallest value

g.N.out("balance").hasLabel(`@double`).min.withGraph(graph).head //should be -245.05
// res55: Double = -245.05

g.N.out("balance").hasLabel(`@double`).min.in("balance").out("name").withGraph(graph).head //should be "Levi"
// res56: Any = Levi
Max

Max-step passes only the traverser with the largest value

g.N.out("balance").hasLabel(`@double`).max.withGraph(graph).head //should be 2230.30
// res57: Double = 2230.3

g.N.out("balance").hasLabel(`@double`).max.in("balance").out("name").withGraph(graph).head //should be "Gray"
// res58: Any = Gray

Rearrange barrier steps

Rearrange barrier steps manipulates the position of all the traversers in the stream.

Order

Order-step sorts the resultset

Head-step takes the first traverser

g.N.head.iri.withGraph(graph).head //takes only the first node
// res59: String = librarian-doc/person/567

g.N.group(_.out("name").head).mapValues(_.iri).withGraph(graph).toList //
// res60: List[(Option[Any], List[String])] = List((Some(Crystal Springs),List(librarian-doc/place/12345)), (Some(San José de Maipo),List(librarian-doc/place/123)), (Some(Yoshio),List(librarian-doc/person/123)), (Some(Levi),List(librarian-doc/person/12345)), (Some(Garrison),List(librarian-doc/person/56789)), (Some(Kevin),List(librarian-doc/person/34567)), (Some(Gray),List(librarian-doc/person/345)), (Some(Talca),List(librarian-doc/place/34567)), (Some(Stan),List(librarian-doc/person/567)), (Some(Haridwar),List(librarian-doc/place/345)))

Last

Last-step takes the last traverser

g.N.last.iri.withGraph(graph).head //takes only the last 12 nodes
// res61: String = librarian-doc/place/34567

g.N.group(_.out("name").last).mapValues(_.iri).withGraph(graph).toList //
// res62: List[(Option[Any], List[String])] = List((Some(Crystal Springs),List(librarian-doc/place/12345)), (Some(San José de Maipo),List(librarian-doc/place/123)), (Some(Yoshio),List(librarian-doc/person/123)), (Some(Levi),List(librarian-doc/person/12345)), (Some(Garrison),List(librarian-doc/person/56789)), (Some(Kevin),List(librarian-doc/person/34567)), (Some(Gray),List(librarian-doc/person/345)), (Some(Talca),List(librarian-doc/place/34567)), (Some(Stan),List(librarian-doc/person/567)), (Some(Haridwar),List(librarian-doc/place/345)))

Count

Count-step returns the number of incoming traversers

g.N.hasLabel(Ontology("https://example.org/Person")).count.withGraph(graph).head //should be 6
// res63: Long = 6

g.N.hasLabel(Ontology("https://example.org/Person")).where(_.out(Property("https://example.org/knows")).count.is(P.gt(1))).count.withGraph(graph).head //should be 5
// res64: Long = 5

g.N.hasLabel(Ontology("https://example.org/Person")).where(_.out(Property("https://example.org/knows")).count.is(P.lt(2))).count.withGraph(graph).head //should be 1
// res65: Long = 1

Side-Effect steps

Side-Effect steps …

Drop

Drop-step removes selected resources from the graph (Only for editable graphs)

Environment steps

Environment steps adjust the context of the traversal

TimeLimit

TimeLimit-step limits the amount of time the rest of the traversal may take

g.N.timeLimit(20).withGraph(graph).toList
// res66: List[lspace.structure.Node] = List(lspace.provider.mem.MemGraph$$anon$7@5db0e4c5, lspace.provider.mem.MemGraph$$anon$7@5db0e407, lspace.provider.mem.MemGraph$$anon$7@5db0e447, lspace.provider.mem.MemGraph$$anon$7@5db0e4d0, lspace.provider.mem.MemGraph$$anon$7@5db0e4a5, lspace.provider.mem.MemGraph$$anon$7@5db0e42b, lspace.provider.mem.MemGraph$$anon$7@5db0e3ec, lspace.provider.mem.MemGraph$$anon$7@5db0e4b6, lspace.provider.mem.MemGraph$$anon$7@5db0e479, lspace.provider.mem.MemGraph$$anon$7@5db0e440)