Graph types
All graph types are either structural elements of the graph or projections thereof. None can be stored as a property value.
Nodes
Nodes are persistent graph elements that can be connected to each other via relationships.
They can have any number of labels that describe their general type. For example, a node representing London may be created with the Place
and City
labels and retrieved by queries using either or both of them.
Nodes have sets of properties to describe all of their salient characteristics. For example, our London node may have the property set: {name: 'London', capital: True, elevation: 11}
.
When querying nodes, multiple labels can be specified. Only nodes that hold all specified labels will be matched:
$ redis-cli GRAPH.QUERY G "MATCH (n:Place:Continent) RETURN n"
Relationships
Relationships are persistent graph elements that connect one node to another.
They must have exactly one type that describes what they represent. For example, a RESIDENT_OF
relationship may be used to connect a Person
node to a City
node.
Relationships are always directed, connecting a source node to its destination.
Like nodes, relationships have sets of properties to describe all of their salient characteristics.
When querying relationships, multiple types can be specified when separated by types. Relationships that hold any of the specified types will be matched:
$ redis-cli GRAPH.QUERY G "MATCH (:Person)-[r:RESIDENT_OF|:VISITOR_TO]->(:Place {name: 'London'}) RETURN r"
Paths
Paths are alternating sequences of nodes and edges, starting and ending with a node.
They are not structural elements in the graph, but can be created and returned by queries.
For example, the following query returns all paths of any length connecting the node London to the node New York:
$ redis-cli GRAPH.QUERY G "MATCH p=(:City {name: 'London'})-[*]->(:City {name: 'New York'}) RETURN p"
Scalar types
All scalar types may be provided by queries or stored as property values on node and relationship objects.
Strings
FalkorDB strings are Unicode character sequences. When using Redis with a TTY (such as invoking FalkorDB commands from the terminal via redis-cli
), some code points may not be decoded, as in:
$ redis-cli GRAPH.QUERY G "RETURN '日本人' as stringval"
1) 1) "stringval"
2) 1) 1) "\xe6\x97\xa5\xe6\x9c\xac\xe4\xba\xba"
Output decoding can be forced using the --raw
flag:
$ redis-cli --raw GRAPH.QUERY G "RETURN '日本人' as stringval"
stringval
日本人
Booleans
Boolean values are specified as true
or false
. Internally, they are stored as numerics, with 1 representing true and 0 representing false. As FalkorDB considers types in its comparisons, 1 is not considered equal to true
:
$ redis-cli GRAPH.QUERY G "RETURN 1 = true"
1) 1) "1 = true"
2) 1) 1) "false"
Integers
All FalkorDB integers are treated as 64-bit signed integers.
Floating-point values
All FalkorDB floating-point values are treated as 64-bit signed doubles.
Geospatial Points
The Point data type is a set of latitude/longitude coordinates, stored within FalkorDB as a pair of 32-bit floats. It is instantiated using the point() function call.
Nulls
In FalkorDB, null
is used to stand in for an unknown or missing value.
Since we cannot reason broadly about unknown values, null
is an important part of FalkorDB’s 3-valued truth table. For example, the comparison null = null
will evaluate to null
, as we lack adequate information about the compared values. Similarly, null in [1,2,3]
evaluates to null
, since the value we’re looking up is unknown.
Unlike all other scalars, null
cannot be stored as a property value.
Collection types
Arrays
Arrays are ordered lists of elements. They can be provided as literals or generated by functions like collect()
. Nested arrays are supported, as are many functions that operate on arrays such as list comprehensions.
Arrays can be stored as property values provided that no array element is of an unserializable type, such as graph entities or null
values.
Maps
Maps are order-agnostic collections of key-value pairs. If a key is a string literal, the map can be accessed using dot notation. If it is instead an expression that evaluates to a string literal, bracket notation can be used:
$ redis-cli GRAPH.QUERY G "WITH {key1: 'stringval', key2: 10} AS map RETURN map.key1, map['key' + 2]"
1) 1) "map.key1"
2) "map['key' + 2]"
2) 1) 1) "stringval"
2) (integer) 10
This aligns with the way that the properties of nodes and relationships can be accessed.
Maps cannot be stored as property values.
Map projections
Maps can be constructed as projections using the syntax alias {.key1 [, ...n]}
. This can provide a useful format for returning graph entities. For example, given a graph with the node (name: 'Jeff', age: 32)
, we can build the projection:
$ redis-cli GRAPH.QUERY G "MATCH (n) RETURN n {.name, .age} AS projection"
1) 1) "projection"
2) 1) 1) "{name: Jeff, age: 32}"
Function calls in map values
The values in maps and map projections are flexible, and can generally refer either to constants or computed values:
$ redis-cli GRAPH.QUERY G "RETURN {key1: 'constant', key2: rand(), key3: toLower('GENERATED') + '_string'} AS map"
1) 1) "map"
2) 1) 1) "{key1: constant, key2: 0.889656, key3: generated_string}"
The exception to this is aggregation functions, which must be computed in a preceding WITH
clause instead of being invoked within the map. This restriction is intentional, as it helps to clearly disambiguate the aggregate function calls and the key values they are grouped by:
$ redis-cli GRAPH.QUERY G "
MATCH (follower:User)-[:FOLLOWS]->(u:User)
WITH u, COUNT(follower) AS count
RETURN u {.name, follower_count: count} AS user"
1) 1) "user"
2) 1) 1) "{name: Jeff, follower_count: 12}"
2) 1) "{name: Roi, follower_count: 18}"