Here you see the syntax of the declaration of Saul graph. Most of these features are unit tested in GraphQueriesTest.
Definition:
val n = node[A]
Get all the instances of a node:
n()
To start querying using a custom collection:
val coll: Iterable[A] = ...
n(coll)
Definition:
val n2 = node[B]
val e = edge(n,n2)
Get all neighbors of all instances of n
:
n() ~> e
Get all neighbors of some of the instances of n
:
n(coll) ~> e
Reverse Query, get all neighbors of all instances of n2
:
n2() ~> -e
Definition:
val p=property[A]{
x : A => property_sensor(x)
}
Get the property of a specific instance x
:
p(x)
It would be nicer if we can have:
x.p
and
n(x) ~> edge1 ~>edge2 p
which provides a collection of all p
property values of all nodes that we get after edge2
.
Properties have a core which is a basic data type b
, such as String
, Int
, etc or an Iterable[b]
.
So property functions should be able to be applied on single instances or a set of instances.
Filter the instances of a node:
def f: A => Boolean = ...
n() filter f
Filter a collection of instances:
n(coll) filter f
Note that this is different from n.filter(f)
or coll.filter(f)
since you can continue the graph query:
n(coll) filter f ~> e
- Applying a property
p
on a set of instancesX
:
node(X).p.aggregation1
- Aggregation functions:
-- Features with nominal values
String aggregations, mainly concatenation
-- Integer and Real Features
Numerical aggregations such as sum, multiplication, max, min, ...
node(n) filter (a logical expression over p)
This implies we need to implement the following functions for properties: equality of one property with a value, equality of two properties, p.contains(x), etc. This seems to be trivial to do or even simply granted by Scala for the most cases because the properties return basic types or collections of them.
val n1 = node[A]
val n2 = node[B]
val n3 = node[C]
val e1 = edge(n1, n2)
val e2 = edge(n2, n3)
n1()
n1() ~> e1 // = n2
n1() ~> e1 ~> e2 // = n3
n3() ~> -e2 // = n2
n3() ~> -e2 ~> -e1 // = n1
##More contextual queries
getting neighbors of a node
n1(a)~>*
getting neighbors of a node within a specific distance:
n1(a)~>e(2)
n1(a)~>e(-2,2)
getting the properties of the neighbors:
n(a)~>e(2).p
n(a)~>e(-2,2).p.aggregate
finding path between two nodes
n1(a).path(n2(b))