In progress, but may be used for a simple things
NB: Built over nightly Rust, but not guaranteed to be up-to-date with the very latest version, since it is was made for fun. While I use it, though, it will appear rather fresh for some time, I suppose.
Cayley is a new graph-driven Database engine from Google, read about it in their Github or in different articles.
API Docs (rustdoc
).
To get a first impression on how it looks in action, see test with queries to 30K-Movie database and path compilation test sources.
Add these lines to your Cargo.toml
:
[dependencies.cayley]
git = "https://github.com/shamansir/cayley-rust"
doc = false
And then, in any file you want to use Cayley, add:
extern crate cayley;
Just don't forget to start Cayley DB itself before every session:
$ ./cayley http --dbpath=<your-database>
To connect to a graph at localhost:64210
, use code like this:
use cayley::{Graph, V1};
let graph = match Graph::new("localhost", 64210, V1) {
Err(error) => panic!(error),
Ok(graph) => graph
};
A simple query pattern looks like this:
use cayley::{GraphNode, GraphNodes};
use cayley::path::{Vertex, Query}; // NB! `Query` is required.
use cayley::selector::AnyNode;
// The query itself
match graph.find(Vertex::start(AnyNode).All()) {
Err(error) => panic!(error.to_string()),
Ok(GraphNodes(nodes)) => {
assert!(nodes.len() > 0);
match nodes.iter().next() {
Some(&GraphNode(ref first_node)) => {
// node is a HashMap<String, String>
println!("{:s}", first_node["id".to_string()]);
},
None => panic!("first node was not found")
}
}
};
NB: Query
trait is required to be imported to give you access to .All()
method of a Vertex
instance. If you feel you don't like it, feel free to support
my post in Rust language discussions.
Look for more complex requests just below.
Due to Rust strict typing, it's hard to transfer free-minded JS-inspired query
syntax from Cayley as-is. Though I decided to leave upper-case style for Query/Path
methods, since i.e. no method can be named in()
in Rust, because in
is a keyword.
Here are some parallels:
Gremlin:
graph.Vertex().All()
cayley-rust:
graph.find(Vertex::start(AnyNode).All())
Gremlin:
graph.Vertex("C").Out("follows").GetLimit(5)
cayley-rust:
graph.find(Vertex::start(Node("C")).OutP(Predicate("follows")).GetLimit(5))
Gremlin:
var friendOfFriend = Morphism().Out("follows").Out("follows")
cayley-rust:
let friendOfFriend = Morphism::start("friendOfFriend")
.OutP(Predicate("follows"))
.OutP(Predicate("follows"));
Gremlin:
g.V("C").Follow(friendOfFriend).Has("status","cool_person")
cayley-rust:
...
use cayley::path::Vertex as V;
let g = Graph::new(...);
let mut friendOfFriend = Morphism::start("friendOfFriend");
friendOfFriend.OutP...;
...
g.find(V::start(Node("C"))
.Follow(&friendOfFriend)
.Has(Predicate("status"), Node("cool_person")));
I have no actual sense if it is correct to use String
/to_string()
in some cases, but I really tried to avoid that as much as possible, and I plan to try
further, if it's not. Or, please, you PRs are welcome.
Things from Gremlin API still not implemented:
query.ToArray()
— not supported with HTTP requestsquery.ToValue()
— not supported with HTTP requestsquery.TagArray()
— not supported with HTTP requestsquery.TagValue()
— not supported with HTTP requestsquery.ForEach(callback), query.ForEach(limit, callback)
a.k.aquery.Map
graph.Emit(data)
- API change: Store
GraphNodes
as a map with immutable strings (see above, p.2 in Possible Drawbacks section); - Preparing
Vertex
for re-use requires to start a query using.From()
selector, and this case should be checked by API for sure; - May be, better Error API;
Thanks to all Rust IRC members for help.