Streaming relationships
To inspect the relationship topology only, the gds.graph.relationships.stream
procedure can be used.
To inspect stored relationship property values, the relationshipProperties.stream
procedure can be used.
This is useful if we ran multiple algorithms in mutate
mode and want to retrieve some or all of the results.
Syntax
CALL gds.graph.relationships.stream(
graphName: String,
relationshipTypes: String or List of Strings,
configuration: Map
)
YIELD
sourceNodeId: Integer,
targetNodeId: Integer,
relationshipType: String
Name | Type | Optional | Description |
---|---|---|---|
graphName |
String |
no |
The name under which the graph is stored in the catalog. |
relationshipTypes |
String or List of Strings |
yes |
The relationship types to stream the relationship properties for graph. |
configuration |
Map |
yes |
Additional parameters to configure streamNodeProperties. |
Name | Type | Default | Description |
---|---|---|---|
concurrency |
Integer |
4 |
The number of concurrent threads. Note, this procedure is always running single-threaded. |
Name | Type | Description |
---|---|---|
sourceNodeId |
Integer |
The id of the source node for the relationship. |
targetNodeId |
Integer |
The id of the target node for the relationship. |
relationshipType |
Integer |
The type of the relationship. |
CALL gds.graph.relationshipProperty.stream(
graphName: String,
relationshipProperty: String,
relationshipTypes: String or List of Strings,
configuration: Map
)
YIELD
sourceNodeId: Integer,
targetNodeId: Integer,
relationshipType: String,
propertyValue: Integer or Float
Name | Type | Optional | Description |
---|---|---|---|
graphName |
String |
no |
The name under which the graph is stored in the catalog. |
relationshipProperty |
String |
no |
The relationship property in the graph to stream. |
relationshipTypes |
String or List of Strings |
yes |
The relationship types to stream the relationship properties for graph. |
configuration |
Map |
yes |
Additional parameters to configure streamNodeProperties. |
Name | Type | Default | Description |
---|---|---|---|
concurrency |
Integer |
4 |
The number of concurrent threads. Note, this procedure is always running single-threaded. |
Name | Type | Description |
---|---|---|
sourceNodeId |
Integer |
The id of the source node for the relationship. |
targetNodeId |
Integer |
The id of the target node for the relationship. |
relationshipType |
Integer |
The type of the relationship. |
propertyValue |
|
The stored property value. |
CALL gds.graph.relationshipProperties.stream(
graphName: String,
relationshipProperties: List of String,
relationshipTypes: String or List of Strings,
configuration: Map
)
YIELD
sourceNodeId: Integer,
targetNodeId: Integer,
relationshipType: String,
relationshipProperty: String,
propertyValue: Integer or Float
Name | Type | Optional | Description |
---|---|---|---|
graphName |
String |
no |
The name under which the graph is stored in the catalog. |
relationshipProperties |
List of String |
no |
The relationship properties in the graph to stream. |
relationshipTypes |
String or List of Strings |
yes |
The relationship types to stream the relationship properties for graph. |
configuration |
Map |
yes |
Additional parameters to configure streamNodeProperties. |
Name | Type | Default | Description |
---|---|---|---|
concurrency |
Integer |
4 |
The number of concurrent threads. Note, this procedure is always running single-threaded. |
Name | Type | Description |
---|---|---|
sourceNodeId |
Integer |
The id of the source node for the relationship. |
targetNodeId |
Integer |
The id of the target node for the relationship. |
relationshipType |
Integer |
The type of the relationship. |
relationshipProperty |
Integer |
The name of the relationship property. |
propertyValue |
|
The stored property value. |
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 over node properties, we are going to create a small graph in Neo4j and project it into our graph catalog.
CREATE
(alice:Person {name: 'Alice'}),
(bob:Person {name: 'Bob'}),
(carol:Person {name: 'Carol'}),
(dave:Person {name: 'Dave'}),
(eve:Person {name: 'Eve'}),
(guitar:Instrument {name: 'Guitar'}),
(synth:Instrument {name: 'Synthesizer'}),
(bongos:Instrument {name: 'Bongos'}),
(trumpet:Instrument {name: 'Trumpet'}),
(alice)-[:LIKES { score: 5 }]->(guitar),
(alice)-[:LIKES { score: 4 }]->(synth),
(alice)-[:LIKES { score: 3, strength: 0.5}]->(bongos),
(bob)-[:LIKES { score: 4 }]->(guitar),
(bob)-[:LIKES { score: 5 }]->(synth),
(carol)-[:LIKES { score: 2 }]->(bongos),
(dave)-[:LIKES { score: 3 }]->(guitar),
(dave)-[:LIKES { score: 1 }]->(synth),
(dave)-[:LIKES { score: 5 }]->(bongos)
MATCH (person:Person)-[r:LIKES]->(instr:Instrument)
RETURN gds.graph.project(
'personsAndInstruments',
person,
instr,
{
sourceNodeLabels: labels(person),
targetNodeLabels: labels(instr),
relationshipType: type(r),
relationshipProperties: r { .score, strength: coalesce(r.strength, 1.0) }
}
)
CALL gds.nodeSimilarity.mutate('personsAndInstruments', { (1)
mutateRelationshipType: 'SIMILAR', (2)
mutateProperty: 'score' (3)
})
1 | Run NodeSimilarity in mutate mode on personsAndInstruments projected graph. |
2 | The algorithm will add relationships of type SIMILAR to the projected graph. |
3 | The algorithm will add relationship property score for each added relationship. |
Topology
The most basic case for streaming relationship information from a named graph is streaming its topology. In this example below we stream relationship topology for all relationship types, represented by source, target and relationship type.
CALL gds.graph.relationships.stream(
'personsAndInstruments' (1)
)
YIELD
sourceNodeId, targetNodeId, relationshipType
RETURN
gds.util.asNode(sourceNodeId).name as source, gds.util.asNode(targetNodeId).name as target, relationshipType
ORDER BY source ASC, target ASC
1 | The name of the projected graph. |
source | target | relationshipType |
---|---|---|
"Alice" |
"Bob" |
"SIMILAR" |
"Alice" |
"Bongos" |
"LIKES" |
"Alice" |
"Carol" |
"SIMILAR" |
"Alice" |
"Dave" |
"SIMILAR" |
"Alice" |
"Guitar" |
"LIKES" |
"Alice" |
"Synthesizer" |
"LIKES" |
"Bob" |
"Alice" |
"SIMILAR" |
"Bob" |
"Dave" |
"SIMILAR" |
"Bob" |
"Guitar" |
"LIKES" |
"Bob" |
"Synthesizer" |
"LIKES" |
"Carol" |
"Alice" |
"SIMILAR" |
"Carol" |
"Bongos" |
"LIKES" |
"Carol" |
"Dave" |
"SIMILAR" |
"Dave" |
"Alice" |
"SIMILAR" |
"Dave" |
"Bob" |
"SIMILAR" |
"Dave" |
"Bongos" |
"LIKES" |
"Dave" |
"Carol" |
"SIMILAR" |
"Dave" |
"Guitar" |
"LIKES" |
"Dave" |
"Synthesizer" |
"LIKES" |
As we can see from the results, we get two relationship types (SIMILAR
and LIKES
).
We can further on filter the relationship types we want to stream.
This can be achieved by passing a second argument to the procedure as demonstrated in the next example.
CALL gds.graph.relationships.stream(
'personsAndInstruments', (1)
['SIMILAR'] (2)
)
YIELD
sourceNodeId, targetNodeId, relationshipType
RETURN
gds.util.asNode(sourceNodeId).name as source, gds.util.asNode(targetNodeId).name as target, relationshipType
ORDER BY source ASC, target ASC
1 | The name of the projected graph. |
2 | List of relationship types we want to stream from, only use the ones we need. |
source | target | relationshipType |
---|---|---|
"Alice" |
"Bob" |
"SIMILAR" |
"Alice" |
"Carol" |
"SIMILAR" |
"Alice" |
"Dave" |
"SIMILAR" |
"Bob" |
"Alice" |
"SIMILAR" |
"Bob" |
"Dave" |
"SIMILAR" |
"Carol" |
"Alice" |
"SIMILAR" |
"Carol" |
"Dave" |
"SIMILAR" |
"Dave" |
"Alice" |
"SIMILAR" |
"Dave" |
"Bob" |
"SIMILAR" |
"Dave" |
"Carol" |
"SIMILAR" |
Single property
The most basic case for streaming relationship properties from a named graph is a single property.
In the example below we stream the relationship property score
.
CALL gds.graph.relationshipProperty.stream(
'personsAndInstruments', (1)
'score' (2)
)
YIELD
sourceNodeId, targetNodeId, relationshipType, propertyValue
RETURN
gds.util.asNode(sourceNodeId).name as source, gds.util.asNode(targetNodeId).name as target, relationshipType, propertyValue
ORDER BY source ASC, target ASC
1 | The name of the projected graph. |
2 | The property we want to stream out. |
source | target | relationshipType | propertyValue |
---|---|---|---|
"Alice" |
"Bob" |
"SIMILAR" |
0.6666666666666666 |
"Alice" |
"Bongos" |
"LIKES" |
3.0 |
"Alice" |
"Carol" |
"SIMILAR" |
0.3333333333333333 |
"Alice" |
"Dave" |
"SIMILAR" |
1.0 |
"Alice" |
"Guitar" |
"LIKES" |
5.0 |
"Alice" |
"Synthesizer" |
"LIKES" |
4.0 |
"Bob" |
"Alice" |
"SIMILAR" |
0.6666666666666666 |
"Bob" |
"Dave" |
"SIMILAR" |
0.6666666666666666 |
"Bob" |
"Guitar" |
"LIKES" |
4.0 |
"Bob" |
"Synthesizer" |
"LIKES" |
5.0 |
"Carol" |
"Alice" |
"SIMILAR" |
0.3333333333333333 |
"Carol" |
"Bongos" |
"LIKES" |
2.0 |
"Carol" |
"Dave" |
"SIMILAR" |
0.3333333333333333 |
"Dave" |
"Alice" |
"SIMILAR" |
1.0 |
"Dave" |
"Bob" |
"SIMILAR" |
0.6666666666666666 |
"Dave" |
"Bongos" |
"LIKES" |
5.0 |
"Dave" |
"Carol" |
"SIMILAR" |
0.3333333333333333 |
"Dave" |
"Guitar" |
"LIKES" |
3.0 |
"Dave" |
"Synthesizer" |
"LIKES" |
1.0 |
As we can see from the results, we get two relationship types (SIMILAR
and LIKES
) that have the score
relationship property.
We can further on filter the relationship types we want to stream, this is demonstrated in the next example.
CALL gds.graph.relationshipProperty.stream(
'personsAndInstruments', (1)
'score', (2)
['SIMILAR'] (3)
)
YIELD
sourceNodeId, targetNodeId, relationshipType, propertyValue
RETURN
gds.util.asNode(sourceNodeId).name as source, gds.util.asNode(targetNodeId).name as target, relationshipType, propertyValue
ORDER BY source ASC, target ASC
1 | The name of the projected graph. |
2 | The property we want to stream out. |
3 | List of relationship types we want to stream the property from, only use the ones we need. |
source | target | relationshipType | propertyValue |
---|---|---|---|
"Alice" |
"Bob" |
"SIMILAR" |
0.6666666666666666 |
"Alice" |
"Carol" |
"SIMILAR" |
0.3333333333333333 |
"Alice" |
"Dave" |
"SIMILAR" |
1.0 |
"Bob" |
"Alice" |
"SIMILAR" |
0.6666666666666666 |
"Bob" |
"Dave" |
"SIMILAR" |
0.6666666666666666 |
"Carol" |
"Alice" |
"SIMILAR" |
0.3333333333333333 |
"Carol" |
"Dave" |
"SIMILAR" |
0.3333333333333333 |
"Dave" |
"Alice" |
"SIMILAR" |
1.0 |
"Dave" |
"Bob" |
"SIMILAR" |
0.6666666666666666 |
"Dave" |
"Carol" |
"SIMILAR" |
0.3333333333333333 |
Multiple properties
It is also possible to stream multiple relationship properties.
CALL gds.graph.relationshipProperties.stream(
'personsAndInstruments', (1)
['score', 'strength'], (2)
['LIKES'] (3)
)
YIELD
sourceNodeId, targetNodeId, relationshipType, relationshipProperty, propertyValue
RETURN
gds.util.asNode(sourceNodeId).name as source, gds.util.asNode(targetNodeId).name as target, relationshipType, relationshipProperty, propertyValue
ORDER BY source ASC, target ASC
1 | The name of the projected graph. |
2 | List of properties we want to stream out, allows us to stream more than one property. |
3 | List of relationship types we want to stream the property from, only use the ones we need. |
source | target | relationshipType | relationshipProperty | propertyValue |
---|---|---|---|---|
"Alice" |
"Bongos" |
"LIKES" |
"score" |
3.0 |
"Alice" |
"Bongos" |
"LIKES" |
"strength" |
0.5 |
"Alice" |
"Guitar" |
"LIKES" |
"score" |
5.0 |
"Alice" |
"Guitar" |
"LIKES" |
"strength" |
1.0 |
"Alice" |
"Synthesizer" |
"LIKES" |
"score" |
4.0 |
"Alice" |
"Synthesizer" |
"LIKES" |
"strength" |
1.0 |
"Bob" |
"Guitar" |
"LIKES" |
"score" |
4.0 |
"Bob" |
"Guitar" |
"LIKES" |
"strength" |
1.0 |
"Bob" |
"Synthesizer" |
"LIKES" |
"score" |
5.0 |
"Bob" |
"Synthesizer" |
"LIKES" |
"strength" |
1.0 |
"Carol" |
"Bongos" |
"LIKES" |
"score" |
2.0 |
"Carol" |
"Bongos" |
"LIKES" |
"strength" |
1.0 |
"Dave" |
"Bongos" |
"LIKES" |
"score" |
5.0 |
"Dave" |
"Bongos" |
"LIKES" |
"strength" |
1.0 |
"Dave" |
"Guitar" |
"LIKES" |
"score" |
3.0 |
"Dave" |
"Guitar" |
"LIKES" |
"strength" |
1.0 |
"Dave" |
"Synthesizer" |
"LIKES" |
"score" |
1.0 |
"Dave" |
"Synthesizer" |
"LIKES" |
"strength" |
1.0 |
Multiple relationship types
Similar to the multiple relationship properties we can stream properties for multiple relationship types.
CALL gds.graph.relationshipProperties.stream(
'personsAndInstruments', (1)
['score'], (2)
['LIKES', 'SIMILAR'] (3)
)
YIELD
sourceNodeId, targetNodeId, relationshipType, relationshipProperty, propertyValue
RETURN
gds.util.asNode(sourceNodeId).name as source, (4)
gds.util.asNode(targetNodeId).name as target, (5)
relationshipType,
relationshipProperty,
propertyValue
ORDER BY source ASC, target ASC
1 | The name of the projected graph. |
2 | List of properties we want to stream out, allows us to stream more than one property. |
3 | List of relationship types we want to stream the property from, only use the ones we need. |
4 | Return the name of the source node. |
5 | Return the name of the target node. |
source | target | relationshipType | relationshipProperty | propertyValue |
---|---|---|---|---|
"Alice" |
"Bob" |
"SIMILAR" |
"score" |
0.6666666666666666 |
"Alice" |
"Bongos" |
"LIKES" |
"score" |
3.0 |
"Alice" |
"Carol" |
"SIMILAR" |
"score" |
0.3333333333333333 |
"Alice" |
"Dave" |
"SIMILAR" |
"score" |
1.0 |
"Alice" |
"Guitar" |
"LIKES" |
"score" |
5.0 |
"Alice" |
"Synthesizer" |
"LIKES" |
"score" |
4.0 |
"Bob" |
"Alice" |
"SIMILAR" |
"score" |
0.6666666666666666 |
"Bob" |
"Dave" |
"SIMILAR" |
"score" |
0.6666666666666666 |
"Bob" |
"Guitar" |
"LIKES" |
"score" |
4.0 |
"Bob" |
"Synthesizer" |
"LIKES" |
"score" |
5.0 |
"Carol" |
"Alice" |
"SIMILAR" |
"score" |
0.3333333333333333 |
"Carol" |
"Bongos" |
"LIKES" |
"score" |
2.0 |
"Carol" |
"Dave" |
"SIMILAR" |
"score" |
0.3333333333333333 |
"Dave" |
"Alice" |
"SIMILAR" |
"score" |
1.0 |
"Dave" |
"Bob" |
"SIMILAR" |
"score" |
0.6666666666666666 |
"Dave" |
"Bongos" |
"LIKES" |
"score" |
5.0 |
"Dave" |
"Carol" |
"SIMILAR" |
"score" |
0.3333333333333333 |
"Dave" |
"Guitar" |
"LIKES" |
"score" |
3.0 |
"Dave" |
"Synthesizer" |
"LIKES" |
"score" |
1.0 |
The properties we want to stream must exist for each specified relationship type. |