Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/knut

python/examples/social_graph.py

"""
Social-graph example
====================

Demonstrates the full round-trip:
  1. Register schemas on the server (Rust side — shown as comment).
  2. Insert a small social graph (vertices + edges) via DoPut.
  3. Fetch it back via DoGet.
  4. Build a NetworkX DiGraph and print basic statistics.

Prerequisite: graphar-flight server running locally on port 50051
with the following schemas registered:

    registry.register(
        "MATCH (n:Person) RETURN n._gar_id AS _gar_id, n.name, n.age",
        Arc::new(Schema::new(vec![
            Field::new("_gar_id", DataType::Int64, false),
            Field::new("name",    DataType::Utf8,  true),
            Field::new("age",     DataType::Int64,  true),
        ])),
    );
    registry.register(
        "MATCH (a:Person)-[r:KNOWS]->(b:Person) RETURN a._gar_id AS src, b._gar_id AS dst, r.since",
        Arc::new(Schema::new(vec![
            Field::new("src",   DataType::Int64, false),
            Field::new("dst",   DataType::Int64, false),
            Field::new("since", DataType::Utf8,  true),
        ])),
    );
"""

import pandas as pd
import networkx as nx
from knut import KnutClient

VERTEX_QUERY = "MATCH (n:Person) RETURN n._gar_id AS _gar_id, n.name, n.age"
EDGE_QUERY   = (
    "MATCH (a:Person)-[r:KNOWS]->(b:Person) "
    "RETURN a._gar_id AS src, b._gar_id AS dst, r.since"
)


def main() -> None:
    client = KnutClient(host="localhost", port=50051)

    # ── 1. Insert vertices ────────────────────────────────────────────────────
    persons = pd.DataFrame({
        "_gar_id": [0, 1, 2, 3],
        "name":    ["Alice", "Bob", "Carol", "Dave"],
        "age":     [30, 25, 35, 28],
    })
    n = client.insert_vertices("Person", persons)
    print(f"Inserted {n} vertices")

    # ── 2. Insert edges ───────────────────────────────────────────────────────
    knows = pd.DataFrame({
        "src":   [0, 0, 1, 2],
        "dst":   [1, 2, 3, 3],
        "since": ["2020-01-01", "2019-06-15", "2021-03-10", "2018-11-01"],
    })
    m = client.insert_edges("Person", "KNOWS", "Person", knows)
    print(f"Inserted {m} edges")

    # ── 3. Build NetworkX graph ───────────────────────────────────────────────
    # Arrow → pandas → NetworkX — no intermediate format conversion needed.
    G = client.to_networkx(
        vertex_query=VERTEX_QUERY,
        edge_query=EDGE_QUERY,
        node_id_col="_gar_id",
        src_col="src",
        dst_col="dst",
        directed=True,
    )

    # ── 4. Inspect ────────────────────────────────────────────────────────────
    print(f"\nGraph: {G.number_of_nodes()} nodes, {G.number_of_edges()} edges")

    print("\nNodes:")
    for node, attrs in G.nodes(data=True):
        print(f"  {node}: {attrs}")

    print("\nEdges:")
    for src, dst, attrs in G.edges(data=True):
        print(f"  {src} → {dst}  {attrs}")

    print("\nIn-degree centrality (top 3):")
    centrality = nx.in_degree_centrality(G)
    for node, score in sorted(centrality.items(), key=lambda x: -x[1])[:3]:
        name = G.nodes[node].get("name", node)
        print(f"  {name}: {score:.4f}")

    print("\nShortest path Alice → Dave:")
    try:
        path = nx.shortest_path(G, source=0, target=3)
        names = [G.nodes[n].get("name", n) for n in path]
        print("  " + " → ".join(names))
    except nx.NetworkXNoPath:
        print("  No path found")


if __name__ == "__main__":
    main()