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

Syntax descriptions of the different operations over relationship types
CALL gds.beta.graph.relationships.stream(
    graphName: String,
    relationshipTypes: List of Strings,
    configuration: Map
)
YIELD
    sourceNodeId: Integer,
    targetNodeId: Integer,
    relationshipType: String
Table 1. Parameters
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.

Table 2. Configuration
Name Type Default Description

concurrency

Integer

4

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

Table 3. Results
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
Table 4. Parameters
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.

Table 5. Configuration
Name Type Default Description

concurrency

Integer

4

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

Table 6. Results
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

  • Integer

  • Float

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
Table 7. Parameters
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.

Table 8. Configuration
Name Type Default Description

concurrency

Integer

4

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

Table 9. Results
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

  • Integer

  • Float

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
Table 10. Parameters
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.

Table 11. Configuration
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 NONE, MIN, MAX, SUM, SINGLE, COUNT. Using map allows specifying aggregations per relationship property. By default we will use the existing aggregation used during the initial projection.

concurrency

Integer

4

yes

The number of concurrent threads used for running the algorithm.

jobId

String

Generated internally

yes

An ID that can be provided to more easily track the algorithm’s progress.

logProgress

Boolean

true

yes

If disabled the progress percentage will not be logged.

Table 12. Results
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
Table 13. Parameters
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.

Table 14. Configuration
Name Type Default Description

concurrency

Integer

4

The number of concurrent threads used for running the procedure. Also provides the default value for writeConcurrency. Note, this procedure is always running single-threaded.

writeConcurrency

Integer

'concurrency'

The number of concurrent threads used for writing the relationship properties. Note, this procedure is always running single-threaded.

Table 15. Results
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
Table 16. Parameters
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.

Table 17. Results
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
Table 18. Parameters
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.

Table 19. Results
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.

Visualization of the example graph
The following Cypher statement will create the example graph in the Neo4j database:
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)
Project the graph:
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.
Compute the Node Similarity in our graph:
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.

Stream all relationships:
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.
Table 20. Results
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.

Stream a single relationship for specific relationship type:
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.
Table 21. Results
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.

Stream a single relationship property:
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.
Table 22. Results
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.

Stream a single relationship property for specific relationship type:
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.
Table 23. Results
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.

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.
Table 24. Results
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.

Stream relationship properties of a multiple relationship projections:
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.
Table 25. Results
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.

Convert relationships from directed to undirected:
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.
Table 26. Results
inputRelationships relationshipsWritten

9

18

Here is an illustration of how the example graph looks in Neo4j after executing the example above.

Visualization of the example graph after converting the relationships to undirected

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

Write relationships to Neo4j:
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.
Table 27. Results
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.

Visualization of the example graph after writing relationships back

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.

Write relationships and their properties to Neo4j:
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.
Table 28. Results
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.

Visualization of the example graph
The following Cypher statement will create the graph for this example in the Neo4j database:
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)
Project the graph:
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.

Write relationships and their properties to Neo4j:
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.
Table 29. Results
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.

Delete all relationships of type 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.
Table 30. Results
graphName relationshipType deletedRelationships deletedProperties

"personsAndInstruments"

"SIMILAR"

10

{score=10}