redis_graph/lib.rs
1//! redis_graph provides a trait with a small number of extension functions for the
2//! [redis](https://docs.rs/redis/) crate to allow working with redis graph
3//! data types that can be installed as a [redis module](https://oss.redislabs.com/redisgraph).
4//!Redis graph operations are mostly using two top level Redis commands
5//!(one for read/write operations and one for read-only operations). In addition
6//!to those there are some more maintenance oriented commands for perfomance, configuration and
7//!clean-up which starting from v0.4.0 are also supported.
8//!The Graph commands are available in synchronous and asynchronous versions.
9//!
10//!The crate is called `redis-graph` and you can depend on it via cargo. You will
11//!also need redis in your dependencies. This version was tested against redis 0.23.0
12//!but should run with versions higher than that.
13//!
14//! ```ini
15//! [dependencies]
16//! redis = "0.23.0"
17//! redis-graph = "0.4.4"
18//! ```
19//!
20//! Or via git:
21//!
22//! ```ini
23//! [dependencies.redis-graph]
24//! git = "https://github.com/tompro/redis_graph.git"
25//! branch = "main"
26//! ```
27//!
28//! With async feature inherited from the [redis](https://docs.rs/redis)
29//! crate (either: 'async-std-comp' or 'tokio-comp):
30//!
31//! ```ini
32//! [dependencies]
33//! redis = "0.22.1"
34//! redis-graph = { version = "0.4.4", features = ['tokio-comp'] }
35//! ```
36//!
37//! # Synchronous usage
38//!
39//! To enable the redis graph commands you simply load the trait
40//! redis_graph::GraphCommands into scope. The redis graph
41//! commands will then be available on your redis connection.
42//! To also have access to the value extractor traits simply import
43//! the whole crate redis_graph::*.
44//!
45//!
46//! ```rust,no_run
47//! # fn run() -> redis::RedisResult<()> {
48//! use redis::Commands;
49//! use redis_graph::*;
50//!
51//! let client = redis::Client::open("redis://127.0.0.1/")?;
52//! let mut con = client.get_connection()?;
53//!
54//! let _:GraphResultSet = con.graph_query(
55//! "my_graph",
56//! "CREATE (:Rider {name:'Valentino Rossi'})-[:rides]->(:Team {name:'Yamaha'})"
57//! )?;
58//!
59//! let _:GraphResultSet = con.graph_ro_query(
60//! "my_graph",
61//! "MATCH (rider:Rider)-[:rides]->(:Team {name:'Yamaha'}) RETURN rider"
62//! )?;
63//! # Ok(()) }
64//! ```
65//!
66//!
67//! # Asynchronous usage
68//!
69//! To enable the redis graph async commands you simply load the
70//! redis_graph::AsyncGraphCommands into the scope. To also have access
71//! to the value extractor traits simply import the whole crate redis_graph::*.
72//!
73//! ```rust,no_run
74//! # #[cfg(any(feature = "tokio-comp", feature = "async-std-comp"))]
75//! # async fn run() -> redis::RedisResult<()> {
76//! use redis::AsyncCommands;
77//! use redis_graph::*;
78//!
79//! let client = redis::Client::open("redis://127.0.0.1/")?;
80//! let mut con = client.get_async_connection().await?;
81//!
82//! let _:GraphResultSet = con.graph_query(
83//! "my_graph",
84//! "CREATE (:Rider {name:'Valentino Rossi'})-[:rides]->(:Team {name:'Yamaha'})"
85//! ).await?;
86//!
87//! let _:GraphResultSet = con.graph_ro_query(
88//! "my_graph",
89//! "MATCH (rider:Rider)-[:rides]->(:Team {name:'Yamaha'}) RETURN rider"
90//! ).await?;
91//! # Ok(()) }
92//! ```
93//!
94//! # Commands
95//!
96//! The following examples work with the synchronous and asynchronous API. For
97//! simplicity all examples will use the synchronous API. To use them async simply
98//! run them within an async function and append the .await after the command call.
99//!
100//! ## GRAPH.QUERY and GRAPH.RO_QUERY
101//! The query command (and read-only alternative) is the only command required for
102//! all graph operations. It will produce a GraphResultSet that contains the
103//! results of the operation. As queries are very flexible a lot of different
104//! data stuctures can be contained in a GraphResultSet.
105//!
106//! ```rust,no_run
107//! # fn run() -> redis::RedisResult<()> {
108//! use redis::Commands;
109//! use redis_graph::*;
110//!
111//! let client = redis::Client::open("redis://127.0.0.1/")?;
112//! let mut con = client.get_connection()?;
113//!
114//! /// A create query returns metadata as a list of strings
115//! let r:GraphResultSet = con.graph_query(
116//! "my_graph",
117//! "CREATE (:Rider {name:'Valentino Rossi'})-[:rides]->(:Team {name:'Yamaha'})"
118//! )?;
119//! assert!(!r.metadata.is_empty());
120//!
121//!
122//! /// This read-only query will return nodes and scalars in the result
123//! let riders = con.graph_ro_query(
124//! "my_graph",
125//! "MATCH (rider:Rider)-[:rides]->(team:Team)
126//! WHERE team.name = 'Yamaha'
127//! RETURN rider, team.name"
128//! )?;
129//!
130//!
131//! /// Data contains a vec of GraphResult with one entry per query match.
132//! assert!(riders.data.len() > 0);
133//!
134//!
135//! /// A GraphResult is indexed with the identifiers used in the RETURN
136//! /// clause of the query. A result has some convenience functions to
137//! /// extract GraphValues (Scalar|Node|Relation) into rust types.
138//! let entry = riders.data.get(0).unwrap();
139//! let rider:Option<&NodeValue> = entry.get_node("rider");
140//! let team_name:Option<String> = entry.get_scalar("team.name");
141//!
142//!
143//! /// Node and Relation values can contain properties for which there are
144//! /// value extractors as well.
145//! let rider_name:Option<String> = rider.unwrap().get_property_option("name");
146//!
147//! # Ok(()) }
148//! ```
149//!
150//! ## GRAPH.PROFILE
151//! Executes a query and produces an execution plan augmented with metrics
152//! for each operation's execution. Returns strings in a list format.
153//!
154//! ```rust,no_run
155//! # fn run() -> redis::RedisResult<()> {
156//! # use redis::Commands;
157//! # use redis_graph::*;
158//! # let client = redis::Client::open("redis://127.0.0.1/")?;
159//! # let mut con = client.get_connection()?;
160//! let profile:Vec<String> = con.graph_profile(
161//! "my_graph",
162//! "MATCH (rider:Rider)-[:rides]->(:Team {name:'Yamaha'}) RETURN rider"
163//! )?;
164//!
165//! # Ok(()) }
166//! ```
167//!
168//! ## GRAPH.DELETE
169//! Completely removes the graph and all of its entities.
170//! ```rust,no_run
171//! # fn run() -> redis::RedisResult<()> {
172//! # use redis::Commands;
173//! # use redis_graph::*;
174//! # let client = redis::Client::open("redis://127.0.0.1/")?;
175//! # let mut con = client.get_connection()?;
176//! let res:String = con.graph_delete("my_graph")?;
177//!
178//! # Ok(()) }
179//! ```
180//!
181//! ## GRAPH.EXPLAIN
182//! Constructs a query execution plan but does not run it. Inspect this
183//! execution plan to better understand how your query will get executed.
184//!
185//! ```rust,no_run
186//! # fn run() -> redis::RedisResult<()> {
187//! # use redis::Commands;
188//! # use redis_graph::*;
189//! # let client = redis::Client::open("redis://127.0.0.1/")?;
190//! # let mut con = client.get_connection()?;
191//! let explanation:Vec<String> = con.graph_explain(
192//! "my_graph",
193//! "MATCH (rider:Rider)-[:rides]->(:Team {name:'Yamaha'}) RETURN rider"
194//! )?;
195//!
196//! # Ok(()) }
197//! ```
198//!
199//! ## GRAPH.SLOWLOG
200//! Returns a list containing up to 10 of the slowest queries issued against the
201//! given graph ID. Results will be read into a list of SlowLogEntry.
202//!
203//! ```rust,no_run
204//! # fn run() -> redis::RedisResult<()> {
205//! # use redis::Commands;
206//! # use redis_graph::*;
207//! # let client = redis::Client::open("redis://127.0.0.1/")?;
208//! # let mut con = client.get_connection()?;
209//! let log:Vec<SlowLogEntry> = con.graph_slowlog("my_graph")?;
210//!
211//! # Ok(()) }
212//! ```
213//!
214//! ## GRAPH.CONFIG
215//! Allows configuring some global behaviour of redis graph for the redis server.
216//!
217//! ```rust,no_run
218//! # fn run() -> redis::RedisResult<()> {
219//! # use redis::Commands;
220//! # use redis_graph::*;
221//! # let client = redis::Client::open("redis://127.0.0.1/")?;
222//! # let mut con = client.get_connection()?;
223//! /// Set a config value. Be aware that setting non config fields here will
224//! /// result in a redis error.
225//! let success:bool = con.graph_config_set("RESULTSET_SIZE", 500)?;
226//!
227//! /// Get a single config value.
228//! let result_set_size:i32 = con.graph_config_get("RESULTSET_SIZE")?;
229//! assert_eq!(result_set_size, 500);
230//!
231//! /// Get all config values
232//! let config: GraphConfig = con.graph_config_get_all()?;
233//! let res_size:Option<u32> = config.get_value("RESULTSET_SIZE")?;
234//! assert_eq!(res_size.unwrap(), 500);
235//!
236//! # Ok(()) }
237//! ```
238#[cfg(any(feature = "tokio-comp", feature = "async-std-comp"))]
239pub use crate::async_commands::AsyncGraphCommands;
240pub use crate::commands::GraphCommands;
241pub use crate::types::*;
242
243#[cfg(any(feature = "tokio-comp", feature = "async-std-comp"))]
244mod async_commands;
245mod commands;
246mod types;