Version 2 API
Version 2 (V2) of the client API improves the user experience and addresses common pitfalls in the GDS Python Client. The new endpoints provide a more modern, type-safe, and intuitive way to interact with the Neo4j Graph Data Science library with a few key features:
-
Improved autocompletion: Better IDE support for discovering available endpoints and their sub-commands.
-
Explicit parameters: Functions now use named, typed parameters instead of a generic
configdictionary, making code more readable and self-documenting. -
Type-safe results: Instead of generic Pandas
Seriesobjects, V2 endpoints return dedicated result types, enabling better static analysis and IDE integration. -
Pythonic naming: Transitioning from CamelCase to snake_case for algorithm and parameter names, following Python’s PEP 8 naming conventions.
In the next major release (2.0), the V2 API will become the default way to call GDS algorithms.
1. Migrating to V2 API
Migrating your existing code to use V2 endpoints involves a few straightforward changes:
-
Update the namespace: Change the endpoint prefix from
gdstogds.v2. -
Standardize naming: Convert algorithm and parameter names from CamelCase to snake_case (for example, replace
pageRankwithpage_rank). -
Use typed results: Access result fields directly as attributes on the returned object instead of using string keys on a
Series(for example, replaceresult["writeMillis"]withresult.write_millis).
| Original | V2 |
|---|---|
|
|
|
|
|
|
|
|
2. Asynchronous execution
Most long-running operations in the V2 API have a non-blocking variant that returns a handle instead of blocking until the work is finished. The handle exposes the job id, lets you poll status, wait for completion, and retrieve results when ready. This is useful when you want to kick off work, do something else, and pick up the result later — possibly from a different process by looking the job up via its id.
Three handle types are returned across the API:
-
ProjectionJobHandle— returned by the async endpoints that produce new graphs. It yields the projected graph and a summary. -
JobHandle— returned by every algorithm’scompute(…)method.stream(),mutate(…), andwrite(…)consume the result, blocking on completion if needed. -
WriteJobHandle— Write back operations started from a genericJobHandleyield aWriteBackResult.
All handles share the same shape:
-
handle.job_id()— the server-assigned job identifier -
handle.status()— current status without blocking -
handle.done()— True once the job has reached a terminal state -
handle.wait()— block until the job finishes -
handle.result(wait=False)— raises JobNotFinishedError if not yet done
2.1. Example: project, compute, and write asynchronously
The following snippet kicks off a remote projection, runs PageRank on the result without blocking, streams the scores, and writes them back — all using handles.
projection_handle = gds.v2.graph.project_native_async(
"people",
"*",
"*"
)
projection_handle.wait() # waits for projection to finish
G, _ = projection_handle.result()
compute_handle = gds.v2.page_rank.compute(G, damping_factor=0.85)
# ... do other work here ...
scores = compute_handle.stream() # blocks on completion, returns a DataFrame
write_handle = compute_handle.write(write_properties="pagerank")
write_result = write_handle.result() # WriteBackResult once the write-back is done
2.2. Recovering a handle via the jobs endpoint
If you lose the original handle — for example, after restarting your client — you can look find jobs via gds.v2.jobs.list() and get the job handle by its id via gds.v2.jobs.get(G, job_id).
The returned handle has the correct concrete type for the underlying job: a ProjectionJobHandle for projection jobs, a WriteJobHandle for write-back jobs, and a plain JobHandle for everything else.
# List all known jobs
handles = gds.v2.jobs.list()
# A previous session started a projection and we kept just the id around.
projection_handle = gds.v2.jobs.get(G, known_projection_job_id)
G, summary = projection_handle.result() # waits if necessary
# Same flow for a write-back job that was started earlier.
write_handle = gds.v2.jobs.get(G, known_write_job_id)
write_result = write_handle.result()