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}"