Streaming nodes

To inspect property values on nodes in GDS graphs, the gds.graph.nodeProperties.stream procedure can be used. This is useful if we have run multiple algorithms in mutate mode and want to retrieve some or all of the results.

Syntax

Syntax descriptions of the different streaming options over nodes
CALL gds.graph.nodeProperty.stream(
    graphName: String,
    nodeProperties: String,
    nodeLabels: String or List of Strings,
    configuration: Map
)
YIELD
    nodeId: Integer,
    propertyValue: Integer or Float or List of Integer or List of Float,
    nodeLabels: List of Strings
Table 1. Parameters
Name Type Optional Description

graphName

String

no

The name under which the graph is stored in the catalog.

nodeProperties

String

no

The node property in the graph to stream.

nodeLabels

String or List of Strings

yes

The node labels to stream the node properties for graph.

configuration

Map

yes

Additional parameters to configure streamNodeProperties.

Table 2. Configuration
Name Type Default Description

concurrency

Integer

4

The number of concurrent threads. Note, this procedure is always running single-threaded.

listNodeLabels

Boolean

false

Whether to return a list of node labels for each node.

Table 3. Results
Name Type Description

nodeId

Integer

The id of the node.

propertyValue

  • Integer

  • Float

  • List of Integer

  • List of Float

The stored property value.

nodeLabels

List of Strings

The node labels of the node.

CALL gds.graph.nodeProperties.stream(
    graphName: String,
    nodeProperties: String or List of Strings,
    nodeLabels: String or List of Strings,
    configuration: Map
)
YIELD
    nodeId: Integer,
    nodeProperty: String,
    propertyValue: Integer or Float or List of Integer or List of Float,
    nodeLabels: List of Strings
Table 4. Parameters
Name Type Optional Description

graphName

String

no

The name under which the graph is stored in the catalog.

nodeProperties

String or List of Strings

no

The node properties in the graph to stream.

nodeLabels

String or List of Strings

yes

The node labels to stream the node properties for graph.

configuration

Map

yes

Additional parameters to configure streamNodeProperties.

Table 5. Configuration
Name Type Default Description

concurrency

Integer

4

The number of concurrent threads. Note, this procedure is always running single-threaded.

listNodeLabels

Boolean

false

Whether to return a list of node labels for each node.

Table 6. Results
Name Type Description

nodeId

Integer

The id of the node.

nodeProperty

String

The name of the node property.

propertyValue

  • Integer

  • Float

  • List of Integer

  • List of Float

The stored property value.

nodeLabels

List of Strings

The node labels of the node.

Examples

All the examples below should be run in an empty database.

The examples use Cypher projections as the norm. Native projections will be deprecated in a future release.

In order to demonstrate the GDS capabilities of streaming node properties, we are going to create a small social network graph in Neo4j and project it into our graph catalog.

The following Cypher statement will create the example graph in the Neo4j database:
CREATE
  (florentin:Person { name: 'Florentin', age: 16 }),
  (adam:Person { name: 'Adam', age: 18 }),
  (veselin:Person { name: 'Veselin', age: 20 }),
  (hobbit:Book { name: 'The Hobbit', numberOfPages: 310 }),
  (florentin)-[:KNOWS { since: 2010 }]->(adam),
  (florentin)-[:KNOWS { since: 2018 }]->(veselin),
  (adam)-[:READ]->(hobbit)
Project the small social network graph:
MATCH (n:Person)-[r:KNOWS|READ]->(m:Person|Book)
RETURN gds.graph.project('socialGraph', n, m,
  {
    sourceNodeLabels: labels(n),
    targetNodeLabels: labels(m),
    sourceNodeProperties: n { .age },
    targetNodeProperties: CASE WHEN m:Person THEN m { .age } ELSE {} END,
    relationshipType: type(r)
  }
)
Compute the Degree Centrality in our social graph:
CALL gds.degree.mutate('socialGraph', {mutateProperty: 'score'})

We can stream node properties stored in a named in-memory graph back to the user. This is useful if we ran multiple algorithms in mutate mode and want to retrieve some or all of the results. This is similar to what an algorithm stream execution mode does, but allows more fine-grained control over the operations.

Single property

In the following, we stream the previously computed scores score.

Stream the score node property:
CALL gds.graph.nodeProperty.stream('socialGraph', 'score')
YIELD nodeId, propertyValue
RETURN gds.util.asNode(nodeId).name AS name, propertyValue AS score
ORDER BY score DESC
Table 7. Results
name score

"Florentin"

2.0

"Adam"

1.0

"Veselin"

0.0

"The Hobbit"

0.0

The above example requires all given properties to be present on at least one node projection, and the properties will be streamed for all such projections.

NodeLabels

The procedure can be configured to stream just the properties for specific node labels.

Stream the score property for Person nodes:
CALL gds.graph.nodeProperty.stream('socialGraph', 'score', ['Person'])
YIELD nodeId, propertyValue
RETURN gds.util.asNode(nodeId).name AS name, propertyValue AS score
ORDER BY score DESC
Table 8. Results
name score

"Florentin"

2.0

"Adam"

1.0

"Veselin"

0.0

It is required, that all specified node labels have the node property.

Multiple Properties

We can also stream several properties at once.

Stream multiple node properties:
CALL gds.graph.nodeProperties.stream('socialGraph', ['score', 'age'])
YIELD nodeId, nodeProperty, propertyValue
RETURN gds.util.asNode(nodeId).name AS name, nodeProperty, propertyValue
ORDER BY name, nodeProperty
Table 9. Results
name nodeProperty propertyValue

"Adam"

"age"

18

"Adam"

"score"

1.0

"Florentin"

"age"

16

"Florentin"

"score"

2.0

"Veselin"

"age"

20

"Veselin"

"score"

0.0

When streaming multiple node properties, the name of each property is included in the result. This adds with some overhead, as each property name must be repeated for each node in the result, but is necessary in order to distinguish properties.

Additionally, when streaming one or more node properties, we can also return the node labels for each individual node by setting the listNodeLabels configuration option.

Stream multiple node properties with labels:
CALL gds.graph.nodeProperties.stream(
  'socialGraph',
  ['score'],
  ['*'],
  { listNodeLabels: true }
)
YIELD nodeId, nodeProperty, propertyValue, nodeLabels
RETURN
  gds.util.asNode(nodeId).name AS name,
  nodeProperty,
  propertyValue,
  nodeLabels
Table 10. Results
name nodeProperty propertyValue nodeLabels

"Florentin"

"score"

2.0

["Person"]

"Adam"

"score"

1.0

["Person"]

"Veselin"

"score"

0.0

["Person"]

"The Hobbit"

"score"

0.0

["Book"]

Single node property access

GDS offers a function to access the property value of a specific node from an in-memory graph directly in a Cypher query.

Syntax

gds.util.nodeProperty(
  graphName: String,
  nodeId: Node or Integer,
  propertyKey: String,
  nodeLabel: String
)
Table 11. Parameters
Name Type Optional Description

graphName

String

no

Name of the graph in the catalog.

nodeId

Integer

no

Id of the node.

propertyKey

String

no

Property key to access.

nodeLabel

String

yes

Label on the node.

If the property value is missing for the given node, null is returned.

Examples

We use the socialGraph with the property score introduced above.

Access a property node property for Florentin:
MATCH (florentin:Person {name: 'Florentin'})
RETURN
  florentin.name AS name,
  gds.util.nodeProperty('socialGraph', florentin, 'score') AS score
Table 12. Results
name score

"Florentin"

2.0