Skip to content

Commit d99decc

Browse files
committed
Implement CollapsPath
1 parent a49f28d commit d99decc

File tree

5 files changed

+147
-0
lines changed

5 files changed

+147
-0
lines changed

graphdatascience/procedure_surface/api/catalog/relationships_endpoints.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,52 @@ def to_undirected(
207207

208208
pass
209209

210+
@abstractmethod
211+
def collapse_path(
212+
self,
213+
G: GraphV2,
214+
path_templates: list[list[str]],
215+
mutate_relationship_type: str,
216+
*,
217+
allow_self_loops: bool = False,
218+
concurrency: int | None = None,
219+
job_id: str | None = None,
220+
sudo: bool = False,
221+
log_progress: bool = True,
222+
username: str | None = None,
223+
) -> CollapsePathResult:
224+
"""
225+
Collapse a path in the graph catalog.
226+
227+
Parameters
228+
----------
229+
230+
G : GraphV2
231+
Name of the generated graph.
232+
path_templates : list[list[str]]
233+
A path template is an ordered list of relationship types used for the traversal. The same relationship type can be added multiple times, in order to traverse them as indicated. And, you may specify several path templates to process in one go.
234+
mutate_relationship_type : str
235+
The name of the new relationship type to be created.
236+
allow_self_loops : bool, default=False
237+
Whether nodes in the graph can have relationships where start and end nodes are the same.
238+
concurrency : int | None, default=None:
239+
Number of concurrent threads to use. Defaults to None.
240+
job_id : str | None, default=None
241+
Unique identifier for the job associated with the graph generation.
242+
sudo : bool | None, default=None
243+
Override memory estimation limits
244+
log_progress : bool | None, default=None
245+
Whether to log progress during graph generation.
246+
username : str | None, default=None
247+
Username of the individual requesting the graph generation.
248+
249+
Returns
250+
-------
251+
CollapsePathResult: meta data about the generated relationships.
252+
"""
253+
254+
pass
255+
210256

211257
class RelationshipsWriteResult(BaseResult):
212258
graph_name: str
@@ -250,6 +296,14 @@ class RelationshipsToUndirectedResult(RelationshipsInverseIndexResult):
250296
relationships_written: int
251297

252298

299+
class CollapsePathResult(BaseResult):
300+
preProcessingMillis: int
301+
computeMillis: int
302+
mutateMillis: int
303+
relationshipsWritten: int
304+
configuration: dict[str, Any]
305+
306+
253307
class Aggregation(str, Enum):
254308
NONE = "NONE"
255309
SINGLE = "SINGLE"

graphdatascience/procedure_surface/arrow/catalog/relationship_arrow_endpoints.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from graphdatascience.procedure_surface.api.catalog.graph_api import GraphV2
1010
from graphdatascience.procedure_surface.api.catalog.relationships_endpoints import (
1111
Aggregation,
12+
CollapsePathResult,
1213
RelationshipsDropResult,
1314
RelationshipsEndpoints,
1415
RelationshipsInverseIndexResult,
@@ -198,3 +199,35 @@ def to_undirected(
198199
)
199200
result = JobClient.get_summary(self._arrow_client, job_id)
200201
return RelationshipsToUndirectedResult(**result)
202+
203+
def collapse_path(
204+
self,
205+
G: GraphV2,
206+
path_templates: list[list[str]],
207+
mutate_relationship_type: str,
208+
*,
209+
allow_self_loops: bool = False,
210+
concurrency: int | None = None,
211+
job_id: str | None = None,
212+
sudo: bool = False,
213+
log_progress: bool = True,
214+
username: str | None = None,
215+
) -> CollapsePathResult:
216+
config = ConfigConverter.convert_to_gds_config(
217+
graph_name=G.name(),
218+
path_templates=path_templates,
219+
mutate_relationship_type=mutate_relationship_type,
220+
allow_self_loops=allow_self_loops,
221+
concurrency=concurrency,
222+
job_id=job_id,
223+
sudo=sudo,
224+
log_progress=log_progress,
225+
username=username,
226+
)
227+
228+
show_progress = self._show_progress and log_progress
229+
job_id = JobClient.run_job_and_wait(
230+
self._arrow_client, "v2/graph.relationships.collapsePath", config, show_progress=show_progress
231+
)
232+
233+
return CollapsePathResult(**JobClient.get_summary(self._arrow_client, job_id))

graphdatascience/procedure_surface/cypher/catalog/relationship_cypher_endpoints.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from graphdatascience.procedure_surface.api.catalog.graph_api import GraphV2
88
from graphdatascience.procedure_surface.api.catalog.relationships_endpoints import (
99
Aggregation,
10+
CollapsePathResult,
1011
RelationshipsDropResult,
1112
RelationshipsEndpoints,
1213
RelationshipsInverseIndexResult,
@@ -225,3 +226,36 @@ def to_undirected(
225226
).squeeze()
226227

227228
return RelationshipsToUndirectedResult(**result.to_dict())
229+
230+
def collapse_path(
231+
self,
232+
G: GraphV2,
233+
path_templates: list[list[str]],
234+
mutate_relationship_type: str,
235+
*,
236+
allow_self_loops: bool = False,
237+
concurrency: int | None = None,
238+
job_id: str | None = None,
239+
sudo: bool = False,
240+
log_progress: bool = True,
241+
username: str | None = None,
242+
) -> CollapsePathResult:
243+
config = ConfigConverter.convert_to_gds_config(
244+
path_templates=path_templates,
245+
mutate_relationship_type=mutate_relationship_type,
246+
allow_self_loops=allow_self_loops,
247+
concurrency=concurrency,
248+
job_id=job_id,
249+
sudo=sudo,
250+
log_progress=log_progress,
251+
username=username,
252+
)
253+
254+
params = CallParameters(
255+
graph_name=G.name(),
256+
config=config,
257+
)
258+
params.ensure_job_id_in_config()
259+
260+
result = self._query_runner.call_procedure(endpoint="gds.collapsePath.mutate", params=params).squeeze()
261+
return CollapsePathResult(**result.to_dict())

graphdatascience/tests/integrationV2/procedure_surface/arrow/catalog/test_relationship_arrow_endpoints.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,16 @@ def test_to_undirected_with_property_aggregation(
231231
assert result.mutate_millis >= 0
232232
assert result.input_relationships == 3
233233
assert result.relationships_written == 6
234+
235+
236+
def test_collapse_path(relationship_endpoints: RelationshipArrowEndpoints, sample_graph: GraphV2) -> None:
237+
result = relationship_endpoints.collapse_path(
238+
G=sample_graph,
239+
path_templates=[["REL", "REL"]],
240+
mutate_relationship_type="FoF",
241+
)
242+
243+
assert result.relationshipsWritten == 3
244+
assert result.mutateMillis >= 0
245+
assert result.preProcessingMillis >= 0
246+
assert result.computeMillis >= 0

graphdatascience/tests/integrationV2/procedure_surface/cypher/catalog/test_relationship_cypher_endpoints.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,16 @@ def test_to_undirected_with_property_aggregation(
252252
assert result.mutate_millis >= 0
253253
assert result.input_relationships == 3
254254
assert result.relationships_written == 6
255+
256+
257+
def test_collapse_path(relationship_endpoints: RelationshipCypherEndpoints, sample_graph: GraphV2) -> None:
258+
result = relationship_endpoints.collapse_path(
259+
G=sample_graph,
260+
path_templates=[["REL", "REL"]],
261+
mutate_relationship_type="FoF",
262+
)
263+
264+
assert result.relationshipsWritten == 3
265+
assert result.mutateMillis >= 0
266+
assert result.preProcessingMillis >= 0
267+
assert result.computeMillis >= 0

0 commit comments

Comments
 (0)