Skip to content
Merged
73 changes: 73 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Examples for lance-graph

## How to Run Examples

Pick one of the two approaches:

### 1) Local build (editable) with maturin

```bash
# From the repo root; installs the Python extension in editable mode
pip install pyarrow # or: uv pip install pyarrow
maturin develop -m python/Cargo.toml

# Run examples
python examples/basic_cypher.py
python examples/kg_traversal.py
```

With `uv` (persistent venv recommended):

```bash
# Create and activate a reusable environment
uv venv .venv && . .venv/bin/activate

# Install dependencies and build editable extension
uv pip install pyarrow
uvx --from maturin maturin develop -m python/Cargo.toml

# Run examples using the venv's Python
python examples/basic_cypher.py
python examples/kg_traversal.py
```

### 2) Install the package, then run

- From PyPI (when published):

```bash
pip install lance-graph pyarrow
python examples/basic_cypher.py
python examples/kg_traversal.py
```

- From git (editable):

```bash
pip install -e python
python examples/basic_cypher.py
python examples/kg_traversal.py
```

### 3) Single-shot with uv (no install, run from source)

uv creates a fresh isolated environment per run. If you prefer a one-liner without installing the package, point `PYTHONPATH` to the source package and let uv provide `pyarrow`:

```bash
PYTHONPATH=python/python uv run --with pyarrow python examples/basic_cypher.py
PYTHONPATH=python/python uv run --with pyarrow python examples/kg_traversal.py
```

## Examples

- `basic_cypher.py`: simple node filter and projection.

```bash
python examples/basic_cypher.py
```

- `kg_traversal.py`: multi-hop traversal on a small synthetic knowledge graph.

```bash
python examples/kg_traversal.py
```
51 changes: 51 additions & 0 deletions examples/basic_cypher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""
Basic Cypher graph query using the lance-graph Python bindings.

Requirements:
- Build/install the Python extension first (from repo root):
maturin develop -m python/Cargo.toml
- Python deps: pyarrow

Run:
python examples/basic_cypher.py
"""

from __future__ import annotations

import pyarrow as pa

from lance_graph import GraphConfigBuilder, CypherQuery


def make_people_batch() -> pa.RecordBatch:
return pa.record_batch(
[
pa.array([1, 2, 3, 4, 5], type=pa.int32()),
pa.array(["Alice", "Bob", "Carol", "David", "Eve"], type=pa.string()),
pa.array([28, 34, 29, 42, 31], type=pa.int32()),
],
names=["person_id", "name", "age"],
)


def main() -> None:
config = (
GraphConfigBuilder()
.with_node_label("Person", "person_id")
.build()
)

query = (
CypherQuery("MATCH (n:Person) WHERE n.age > 30 RETURN n.name")
.with_config(config)
)

datasets = {"Person": make_people_batch()}
result = query.execute(datasets)

# Convert to a simple Python dict for display
print(result.to_pydict())


if __name__ == "__main__":
main()
65 changes: 65 additions & 0 deletions examples/kg_traversal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"""
Simple knowledge-graph multi-hop traversal with lance-graph Python bindings.

Requirements:
- Build/install the Python extension first (from repo root):
maturin develop -m python/Cargo.toml
- Python deps: pyarrow

Run:
python examples/kg_traversal.py
"""

from __future__ import annotations

import pyarrow as pa

from lance_graph import GraphConfigBuilder, CypherQuery


def make_people_batch(n: int = 6) -> pa.RecordBatch:
return pa.record_batch(
[
pa.array(list(range(1, n + 1)), type=pa.int32()),
pa.array([f"P{i}" for i in range(1, n + 1)], type=pa.string()),
],
names=["person_id", "name"],
)


def make_friendship_batch(n: int = 6) -> pa.RecordBatch:
# Create a simple ring: 1->2->3->...->n->1
src = list(range(1, n + 1))
dst = [i + 1 if i < n else 1 for i in src]
return pa.record_batch(
[pa.array(src, type=pa.int32()), pa.array(dst, type=pa.int32())],
names=["person1_id", "person2_id"],
)


def main() -> None:
config = (
GraphConfigBuilder()
.with_node_label("Person", "person_id")
.with_relationship("FRIEND_OF", "person1_id", "person2_id")
.build()
)

# Two-hop traversal from a person to friend-of-a-friend
query = (
CypherQuery(
"MATCH (a:Person)-[:FRIEND_OF]->(b:Person)-[:FRIEND_OF]->(c:Person) RETURN a.name, c.name"
)
.with_config(config)
)

datasets = {
"Person": make_people_batch(),
"FRIEND_OF": make_friendship_batch(),
}
result = query.execute(datasets)
print(result.to_pydict())


if __name__ == "__main__":
main()
4 changes: 4 additions & 0 deletions python/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub struct BackgroundExecutor {
}

impl BackgroundExecutor {
#[allow(dead_code)]
pub fn get_runtime_handle(&self) -> Option<tokio::runtime::Handle> {
Some(self.runtime.handle().clone())
}
Expand All @@ -50,6 +51,7 @@ impl BackgroundExecutor {
///
/// This method is safe to use with inputs that may reference a Rust async
/// runtime.
#[allow(dead_code)]
pub fn spawn<T>(&self, py: Option<Python<'_>>, task: T) -> PyResult<T::Output>
where
T: Future + Send + 'static,
Expand All @@ -63,6 +65,7 @@ impl BackgroundExecutor {
}
}

#[allow(dead_code)]
fn spawn_impl<T>(&self, task: T) -> PyResult<T::Output>
where
T: Future + Send + 'static,
Expand Down Expand Up @@ -103,6 +106,7 @@ impl BackgroundExecutor {
}

/// Spawn a task in the background
#[allow(dead_code)]
pub fn spawn_background<T>(&self, py: Option<Python<'_>>, task: T)
where
T: Future + Send + 'static,
Expand Down
27 changes: 27 additions & 0 deletions rust/lance-graph/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,33 @@ Numbers are illustrative; your hardware, compiler, and runtime load will affect

Python bindings for this crate live under `python/src/graph.rs` and expose the same configuration and query APIs via PyO3.

### Python Examples

See top-level `examples/` for runnable Python examples:

- `basic_cypher.py`: simple node filter and projection against in-memory Arrow batches.
- `kg_traversal.py`: two-hop traversal on a small synthetic knowledge graph.

Setup and run (from repo root):

```bash
Option A - Local build (editable):

```bash
maturin develop -m python/Cargo.toml
python examples/basic_cypher.py
python examples/kg_traversal.py
```

Option B - Using uv:

```bash
uvx --from maturin maturin develop -m python/Cargo.toml
uv run --with pyarrow python examples/basic_cypher.py
uv run --with pyarrow python examples/kg_traversal.py
```
```

## License

Apache-2.0. See the top-level LICENSE file for details.
Loading