Skip to content

Commit ac15016

Browse files
committed
Implement CollapsPath
1 parent 9039753 commit ac15016

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
@@ -208,6 +208,52 @@ def to_undirected(
208208

209209
pass
210210

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

212258
class RelationshipsWriteResult(BaseResult):
213259
graph_name: str
@@ -251,6 +297,14 @@ class RelationshipsToUndirectedResult(RelationshipsInverseIndexResult):
251297
relationships_written: int
252298

253299

300+
class CollapsePathResult(BaseResult):
301+
preProcessingMillis: int
302+
computeMillis: int
303+
mutateMillis: int
304+
relationshipsWritten: int
305+
configuration: dict[str, Any]
306+
307+
254308
class Aggregation(str, Enum):
255309
NONE = "NONE"
256310
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
@@ -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,
@@ -197,3 +198,35 @@ def to_undirected(
197198
)
198199
result = JobClient.get_summary(self._arrow_client, job_id)
199200
return RelationshipsToUndirectedResult(**result)
201+
202+
def collapse_path(
203+
self,
204+
G: GraphV2,
205+
path_templates: list[list[str]],
206+
mutate_relationship_type: str,
207+
*,
208+
allow_self_loops: bool = False,
209+
concurrency: int | None = None,
210+
job_id: str | None = None,
211+
sudo: bool = False,
212+
log_progress: bool = True,
213+
username: str | None = None,
214+
) -> CollapsePathResult:
215+
config = ConfigConverter.convert_to_gds_config(
216+
graph_name=G.name(),
217+
path_templates=path_templates,
218+
mutate_relationship_type=mutate_relationship_type,
219+
allow_self_loops=allow_self_loops,
220+
concurrency=concurrency,
221+
job_id=job_id,
222+
sudo=sudo,
223+
log_progress=log_progress,
224+
username=username,
225+
)
226+
227+
show_progress = self._show_progress and log_progress
228+
job_id = JobClient.run_job_and_wait(
229+
self._arrow_client, "v2/graph.relationships.collapsePath", config, show_progress=show_progress
230+
)
231+
232+
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
@@ -5,6 +5,7 @@
55
from graphdatascience.procedure_surface.api.catalog.graph_api import GraphV2
66
from graphdatascience.procedure_surface.api.catalog.relationships_endpoints import (
77
Aggregation,
8+
CollapsePathResult,
89
RelationshipsDropResult,
910
RelationshipsEndpoints,
1011
RelationshipsInverseIndexResult,
@@ -224,3 +225,36 @@ def to_undirected(
224225
).squeeze()
225226

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