Relationship operations
The Neo4j Graph Data Science Library provides multiple operations to work with relationships and their properties stored in a projected graphs.
Relationship properties are either added during the graph projection or when using the mutate
mode of our graph algorithms.
To inspect the relationship topology only, the gds.beta.graph.relationships.stream
procedure can be used.
To inspect stored relationship property values, the streamRelationshipProperties
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.
To persist relationship types in a Neo4j database, we can use gds.graph.relationship.write
.
Similar to streaming relationship topologies or properties, it is also possible to write back to Neo4j.
This is similar to what an algorithm write
execution mode does, but allows more fine-grained control over the operations.
By default, no relationship properties will be written. To write relationship properties, these have to be explicitly specified.
We can also remove relationships from a named graph in the catalog. This is useful to free up main memory or to remove accidentally added relationship types.
1. Syntax
CALL gds.beta.graph.relationships.stream(
graphName: String,
relationshipTypes: 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 |
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: 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 |
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: 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 |
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. |
CALL gds.beta.graph.relationships.toUndirected(
graphName: String,
configuration: Map
)
YIELD
inputRelationships: Integer,
relationshipsWritten: Integer,
mutateMillis: Integer,
postProcessingMillis: Integer,
preProcessingMillis: Integer,
computeMillis: Integer,
configuration: Map
Name | Type | Optional | Description |
---|---|---|---|
graphName |
String |
no |
The name under which the graph is stored in the catalog. |
configuration |
Map |
yes |
Additional parameters to configure streamNodeProperties. |
Name | Type | Default | Optional | Description |
---|---|---|---|---|
relationshipType |
String |
n/a |
no |
The relationship type to make undirected. |
mutateRelationshipType |
String |
n/a |
no |
The relationship type to be added to the graph. |
aggregation |
Map or String |
n/a |
no |
Handling of parallel relationships. Allowed values are |
Integer |
4 |
yes |
The number of concurrent threads used for running the algorithm. |
|
String |
Generated internally |
yes |
An ID that can be provided to more easily track the algorithm’s progress. |
|
Boolean |
true |
yes |
If disabled the progress percentage will not be logged. |
Name | Type | Description |
---|---|---|
inputRelationships |
Integer |
The number of relationships that were processed. |
relationshipsWritten |
Integer |
The number of relationships that were added. |
preProcessingMillis |
Integer |
Milliseconds for preprocessing the graph. |
computeMillis |
Integer |
Milliseconds for running the algorithm. |
postProcessingMillis |
Integer |
Unused. |
mutateMillis |
Integer |
Milliseconds for adding relationships to the projected graph. |
configuration |
Map |
The configuration used for running the algorithm. |
CALL gds.graph.relationship.write(
graphName: String,
relationshipType: String,
relationshipProperty: String,
configuration: Map
)
YIELD
writeMillis: Integer,
graphName: String,
relationshipType: String,
relationshipsWritten: Integer,
relationshipProperty: String,
propertiesWritten: Integer
Name | Type | Optional | Description |
---|---|---|---|
graphName |
String |
no |
The name under which the graph is stored in the catalog. |
relationshipType |
String |
no |
The relationship type in the graph to write back. |
relationshipProperty |
String |
yes |
The relationship property to write back. |
configuration |
Map |
yes |
Additional parameters to configure writeRelationship. |
Name | Type | Default | Description |
---|---|---|---|
concurrency |
Integer |
4 |
The number of concurrent threads used for running the procedure. Also provides the default value for |
writeConcurrency |
Integer |
'concurrency' |
The number of concurrent threads used for writing the relationship properties. Note, this procedure is always running single-threaded. |
Name | Type | Description |
---|---|---|
writeMillis |
Integer |
Milliseconds for writing result data back to Neo4j. |
graphName |
String |
The name of a graph stored in the catalog. |
relationshipType |
String |
The type of the relationship that was written. |
relationshipsWritten |
Integer |
Number relationships written. |
relationshipProperty |
String |
The name of the relationship property that was written. |
propertiesWritten |
Integer |
Number relationships properties written. |
CALL gds.graph.relationshipProperties.write(
graphName: String,
relationshipType: String,
relationshipProperties: List of String,
configuration: Map
)
YIELD
writeMillis: Integer,
graphName: String,
relationshipType: String,
relationshipsWritten: Integer,
relationshipProperties: List of String,
propertiesWritten: Integer
Name | Type | Optional | Description |
---|---|---|---|
graphName |
String |
no |
The name under which the graph is stored in the catalog. |
relationshipType |
String |
no |
The relationship type in the graph to write back. |
relationshipProperties |
String |
yes |
The relationship properties to write back. |
configuration |
Map |
yes |
Additional parameters to configure the procedure. |
Name | Type | Description |
---|---|---|
writeMillis |
Integer |
Milliseconds for writing result data back to Neo4j. |
graphName |
String |
The name of a graph stored in the catalog. |
relationshipType |
String |
The type of the relationship that was written. |
relationshipsWritten |
Integer |
Number relationships written. |
relationshipProperties |
String |
The name of the relationship properties that were written. |
propertiesWritten |
Integer |
Number relationships properties written. |
CALL gds.graph.relationships.drop(
graphName: String,
relationshipType: String
)
YIELD
graphName: String,
relationshipType: String,
deletedRelationships: Integer,
deletedProperties: Map
Name | Type | Optional | Description |
---|---|---|---|
graphName |
String |
no |
The name under which the graph is stored in the catalog. |
relationshipType |
String |
no |
The relationship type in the graph to remove. |
Name | Type | Description |
---|---|---|
graphName |
String |
The name of a graph stored in the catalog. |
relationshipType |
String |
The type of the removed relationships. |
deletedRelationships |
Integer |
Number of removed relationships from the in-memory graph. |
deletedProperties |
Integer |
Map where the key is the name of the relationship property, and the value is the number of removed properties under that name. |
2. Examples
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)
CALL gds.graph.project(
'personsAndInstruments',
['Person', 'Instrument'], (1)
{
LIKES: {
type: 'LIKES', (2)
properties: {
strength: { (3)
property: 'strength',
defaultValue: 1.0
},
score: {
property: 'score' (4)
}
}
}
}
)
1 | Project node labels Person and Instrument . |
2 | Project relationship type LIKES . |
3 | Project property strength of relationship type LIKES setting a default value of 1.0 because not all relationships have that property. |
4 | Project property score of relationship type LIKES . |
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. |
2.1. Stream
2.1.1. 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.beta.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.beta.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" |
2.1.2. 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 |
2.1.3. 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 |
2.1.4. 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. |
2.2. Convert to undirected
Some algorithms such as Triangle Count and Link Prediction expect undirected relationships. The following shows how to convert the relationships of type LIKES
in the graph from directed to undirected by creating an undirected relationship of new type INTERACTS
.
CALL gds.beta.graph.relationships.toUndirected(
'personsAndInstruments', (1)
{relationshipType: 'LIKES', mutateRelationshipType: 'INTERACTS'} (2)
)
YIELD
inputRelationships, relationshipsWritten
1 | The name of the projected graph. |
2 | A map that includes the relationship type to make undirected and the relationship type to be added to the graph. |
inputRelationships | relationshipsWritten |
---|---|
9 |
18 |
Here is an illustration of how the example graph looks in Neo4j after executing the example above.
2.3. Write
We can write relationships stored in a named in-memory graph back to Neo4j. This can be used to write algorithm results (for example from Node Similarity) or relationships that have been aggregated during graph creation.
The relationships to write are specified by a relationship type.
Relationships are always written using a single thread. |
2.3.1. Relationship type
CALL gds.graph.relationship.write(
'personsAndInstruments', (1)
'SIMILAR' (2)
)
YIELD
graphName, relationshipType, relationshipProperty, relationshipsWritten, propertiesWritten
1 | The name of the projected graph. |
2 | The relationship type we want to write back to the Neo4j database. |
graphName | relationshipType | relationshipProperty | relationshipsWritten | propertiesWritten |
---|---|---|---|---|
"personsAndInstruments" |
"SIMILAR" |
null |
10 |
0 |
By default, no relationship properties will be written, as it can be seen from the results, the relationshipProperty
value is null
and propertiesWritten
are 0
.
Here is an illustration of how the example graph looks in Neo4j after executing the example above.
The SIMILAR
relationships have been added to the underlying database and can be used in Cypher queries or for projecting to in-memory graph for running algorithms.
The relationships in this example are undirected because we used Node Similarity to mutate the in-memory graph and this algorithm creates undirected relationships, this may not be the case if we use different algorithms.
2.3.2. Relationship type with property
To write relationship properties, these have to be explicitly specified.
CALL gds.graph.relationship.write(
'personsAndInstruments', (1)
'SIMILAR', (2)
'score' (3)
)
YIELD
graphName, relationshipType, relationshipProperty, relationshipsWritten, propertiesWritten
1 | The name of the projected graph. |
2 | The relationship type we want to write back to the Neo4j database. |
3 | The property name of the relationship we want to write back to the Neo4j database. |
graphName | relationshipType | relationshipProperty | relationshipsWritten | propertiesWritten |
---|---|---|---|---|
"personsAndInstruments" |
"SIMILAR" |
"score" |
10 |
10 |
2.3.3. Relationship type with multiple properties
In order to demonstrate writing relationships with multiple properties back to Neo4j we will create a small graph in the database first.
CREATE
(alice:Buyer {name: 'Alice'}),
(instrumentSeller:Seller {name: 'Instrument Seller'}),
(bob:Buyer {name: 'Bob'}),
(carol:Buyer {name: 'Carol'}),
(alice)-[:PAYS { amount: 1.0}]->(instrumentSeller),
(alice)-[:PAYS { amount: 2.0}]->(instrumentSeller),
(alice)-[:PAYS { amount: 3.0}]->(instrumentSeller),
(alice)-[:PAYS { amount: 4.0}]->(instrumentSeller),
(alice)-[:PAYS { amount: 5.0}]->(instrumentSeller),
(alice)-[:PAYS { amount: 6.0}]->(instrumentSeller),
(bob)-[:PAYS { amount: 3.0}]->(instrumentSeller),
(bob)-[:PAYS { amount: 4.0}]->(instrumentSeller),
(carol)-[:PAYS { amount: 5.0}]->(bob),
(carol)-[:PAYS { amount: 6.0}]->(bob)
CALL gds.graph.project(
'aggregatedGraph',
['Buyer', 'Seller'], (1)
{
PAID: { (2)
type: 'PAYS', (3)
properties: {
totalAmount: { property: 'amount', aggregation: 'SUM' }, (4)
numberOfPayments: { property: 'amount', aggregation: 'COUNT' } (5)
}
}
}
)
1 | Project node labels Buyer and Seller . |
2 | Project relationship type PAID to the in-memory graph. |
3 | Use relationship type PAYS from the Neo4j database graph. |
4 | Project property totalAmount of relationship type PAYS using SUM aggregation. |
5 | Project property numberOfPayments of relationship type PAYS using COUNT aggregation. |
As we can see the Neo4j graph contains some parallel relationships. We use GDS projection to condense these into single relationships between the nodes. In this example we want to track how many times someone paid someone and what is the total amount of all payments.
To write relationship properties, these have to be explicitly specified.
CALL gds.graph.relationshipProperties.write(
'aggregatedGraph', (1)
'PAID', (2)
['totalAmount', 'numberOfPayments'], (3)
{}
)
YIELD
graphName, relationshipType, relationshipProperties, relationshipsWritten, propertiesWritten
1 | The name of the projected graph. |
2 | The relationship type we want to write back to the Neo4j database. |
3 | The property names of the relationship we want to write back to the Neo4j database. |
graphName | relationshipType | relationshipProperties | relationshipsWritten | propertiesWritten |
---|---|---|---|---|
"aggregatedGraph" |
"PAID" |
[totalAmount, numberOfPayments] |
3 |
6 |
2.4. Delete
We can delete all relationships of a given type from a named graph in the catalog. This is useful to free up main memory or to remove accidentally added relationship types.
Deleting relationships of a given type is only possible if it is not the last relationship type present in the graph. If we still want to delete these relationships we need to drop the graph instead. |
SIMILAR
from a named graph:CALL gds.graph.relationships.drop(
'personsAndInstruments', (1)
'SIMILAR' (2)
)
YIELD
graphName, relationshipType, deletedRelationships, deletedProperties
1 | The name of the projected graph. |
2 | The relationship type we want to delete from the projected graph. |
graphName | relationshipType | deletedRelationships | deletedProperties |
---|---|---|---|
"personsAndInstruments" |
"SIMILAR" |
10 |
{score=10} |
Was this page helpful?