Cypher-compatible front-end for petgraph:
build, query, and mutate graphs with
openCypher-compatible queries.
This project is independent and is not affiliated with, endorsed by, or sponsored by Neo4j, Inc. Cypher® and Neo4j® are registered trademarks of Neo4j, Inc.
petgraph-decypher is both:
- A Cypher-driven graph builder (
CREATE/MERGE), and - A query engine for executing read and mutation queries on
petgraph::Graph.
You can start from Cypher or from an existing graph and run Cypher against it.
use petgraph_decypher::build_graph_from_cypher;
let graph = build_graph_from_cypher(
r#"CREATE (a:Person {name: "Alice"})-[:KNOWS]->(b:Person {name: "Bob"})"#,
)
.unwrap();
assert_eq!(graph.node_count(), 2);
assert_eq!(graph.edge_count(), 1);| Feature | Status |
|---|---|
Build graphs with CREATE / MERGE |
✅ |
Read queries: MATCH, WHERE, RETURN, OPTIONAL MATCH |
✅ |
Projection features: DISTINCT, ORDER BY, SKIP, LIMIT |
✅ |
Mutation queries: CREATE, MERGE, SET, REMOVE, [DETACH] DELETE |
✅ |
Scalar functions (e.g. size, toString, toUpper, toLower, trim) |
✅ |
| Multiple clauses / semicolon-separated statements | ✅ |
| Multi-label nodes and undirected relationships | ✅ |
| String, integer, float, bool, null, list, map values | ✅ |
| Capability | Status |
|---|---|
Parameterized queries ($param) |
🚧 planned |
Variable-length paths (*1..3) |
🚧 planned |
| Native subgraph selection as a first-class query output | 🚧 planned |
| End-to-end Cypher subgraph -> petgraph algorithm -> Cypher-style projection helpers | 🚧 planned |
// Parse only – returns the HIR-backed query plan
let query = petgraph_decypher::parse_cypher("CREATE (n:Person {name: \"Alice\"})")
.unwrap();
// Parse + build graph – executes CREATE/MERGE clauses
let graph = petgraph_decypher::build_graph_from_cypher(
"CREATE (a)-[:KNOWS]->(b)"
)
.unwrap();
// Read-only query execution via PetgraphCypher trait
use petgraph_decypher::PetgraphCypher;
let result = graph.cypher("MATCH (n) RETURN n").unwrap();
// Mutating query execution via PetgraphCypher trait
graph.cypher_mut("CREATE (n:Person {name: \"Alice\"})").unwrap();use petgraph::Graph;
use petgraph_decypher::{CypherValue, EdgeData, NodeData, PetgraphCypher};
let mut graph = Graph::<NodeData, EdgeData>::new();
let a = graph.add_node(NodeData {
variable: None,
labels: vec!["Person".into()],
properties: std::collections::HashMap::from([(
"name".into(),
CypherValue::String("Alice".into()),
)]),
});
let b = graph.add_node(NodeData {
variable: None,
labels: vec!["Person".into()],
properties: std::collections::HashMap::from([(
"name".into(),
CypherValue::String("Bob".into()),
)]),
});
graph.add_edge(
a,
b,
EdgeData {
variable: None,
rel_type: Some("KNOWS".into()),
properties: Default::default(),
},
);
let rows: Vec<_> = graph
.cypher("MATCH (p:Person)-[:KNOWS]->(q:Person) RETURN p.name AS from, q.name AS to")
.unwrap()
.collect();
assert_eq!(rows.len(), 1);use petgraph_decypher::{PetgraphCypher, build_graph_from_cypher};
let mut graph = build_graph_from_cypher(r#"CREATE (p:Person {name: "Alice"})"#).unwrap();
graph.cypher_mut(r#"MATCH (p:Person {name: "Alice"}) SET p.role = "Archaeologist""#).unwrap();
graph.cypher_mut(r#"MATCH (p:Person {name: "Alice"}) REMOVE p.role"#).unwrap();build_graph_from_cypher_typed supports domain-specific node and edge weights via
CypherNode and CypherEdge.
For a complete working reference, see:
tests/builder_tests.rs(build_graph_typed_with_custom_types)tests/query_tests.rs(query_match_all_nodes_with_custom_weights)
Today, you can already compose Cypher selection with petgraph algorithms in user code:
- Build/load the graph.
- Use Cypher to select the slice of interest (e.g. nodes/relationships by label/property).
- Run a petgraph algorithm on that selection.
- Map algorithm output back to original node properties.
The examples/indiana_jones.rs example demonstrates the first two steps with read + mutation queries.
Each petgraph node carries a NodeData value:
pub struct NodeData {
pub variable: Option<String>,
pub labels: Vec<String>,
pub properties: HashMap<String, CypherValue>,
}NodeData implements CypherNode, and its property map is exposed through
CypherProperties::get.
Each petgraph edge carries an EdgeData value:
pub struct EdgeData {
pub variable: Option<String>,
pub rel_type: Option<String>,
pub properties: HashMap<String, CypherValue>,
}EdgeData implements CypherEdge, and exposes relationship properties through
CypherProperties::get.
Licensed under either of EUPL-1.2, MIT or Apache-2.0 at your option.
