Learn

How to query Graph data in Redis using Rust

Ajeet Raina
Author
Ajeet Raina, Former Developer Growth Manager at Redis
END-OF-LIFE NOTICE

Redis is phasing out RedisGraphThis blog post explains the motivation behind this decision and the implications for existing Redis customers and community members.

End of support is scheduled for January 31, 2025.

RedisGraph is the first queryable Property Graph database to use sparse matrices to represent the adjacency matrix in graphs and linear algebra to query the graph. RedisGraph is based on a unique approach and architecture that translates Cypher queries to matrix operations executed over a GraphBLAS engine. This new design allows use cases like social graph operation, fraud detection, and real-time recommendation to be executed 10x – 600x faster than any other graph database. Undoubtedly, it is the fastest graph database that processes complex graph operations in real time, 10x – 600x faster than any other graph database. It primariy shows how your data is connected through multiple visualization integrations including RedisInsight, Linkurious, and Graphileon.

RedisGraph is a graph database developed from scratch on top of Redis, using the new Redis Modules API to extend Redis with new commands and capabilities. Its main features include: Simple, fast indexing and querying data stored in RAM using memory-efficient custom data structure. Redis Graph is a directed graph where both nodes and relationships are typed - nodes with labels and edges with types. Node/s and edges can and often do contain properties like columns in a SQL-db or keys in a document store.The newer RedisGraph 2.0 benchmark reveals a significant improvements on parallel workload (multiple clients) with a latency improvements up to 6x and throughput improvements up to 5x when performing graph traversals.

Below are the primary use cases of RedisGraph:

  • Recommendation: It allows you to rapidly find connections between your customers and the experiences they want by examining the relationships between them.
  • Graph-aided search: It allows you to search for single or multiple words or phrases and execute full-text and linguistic queries and implementation in real time over your graph structure.
  • Identity and access management: It allows you to define complex resources access permissions as a graph and enable rapid real-time verification of these permissions with a single query.

RedisGraph Rust Client#

The Rust programming language is blazingly fast and memory-efficient: with no runtime or garbage collector, it can power performance-critical services, run on embedded devices, and easily integrate with other languages. It is an open-source project developed originally at Mozilla Research. The Rust Library is the foundation of portable Rust software, a set of minimal and battle-tested shared abstractions for the broader Rust ecosystem.

redisgraph-rs is an idiomatic Rust client for RedisGraph, the graph database by Redis.This crate parses responses from RedisGraph and converts them into ordinary Rust values. It exposes a very flexible API that allows you to retrieve a single value, a single record or multiple records using only one function: Graph::query.

Follow the steps below to get started with RedisGraph with Rust:

Step 1. Run Redis Stack Docker container#

 docker run -p 6379:6379 --name redis/redis-stack

Step 2. Verify if RedisGraph module is loaded#

 info modules
 # Modules
 module:name=graph,ver=20405,api=1,filters=0,usedby=[],using=[],options=[]

Step 3. Install Rust#

 brew install rust

Step 4. Clone the repository#

  git clone https://github.com/malte-v/redisgraph-rs

Step 5. Write a rust program#

Copy the below content and save it as "main.rs" under src directory.

 use redis::Client;
 use redisgraph::{Graph, RedisGraphResult};

 fn main() -> RedisGraphResult<()> {
   let client = Client::open("redis://127.0.0.1:6379")?;
   let mut connection = client.get_connection()?;

   let mut graph = Graph::open(connection, "MotoGP".to_string())?;

   // Create six nodes (three riders, three teams) and three relationships between them.
   graph.mutate("CREATE (:Rider {name: 'Valentino Rossi', birth_year: 1979})-[:rides]->(:Team {name: 'Yamaha'}), \
       (:Rider {name:'Dani Pedrosa', birth_year: 1985, height: 1.58})-[:rides]->(:Team {name: 'Honda'}), \
       (:Rider {name:'Andrea Dovizioso', birth_year: 1986, height: 1.67})-[:rides]->(:Team {name: 'Ducati'})")?;

   // Get the names and birth years of all riders in team Yamaha.
   let results: Vec<(String, u32)> = graph.query("MATCH (r:Rider)-[:rides]->(t:Team) WHERE t.name = 'Yamaha' RETURN r.name, r.birth_year")?;
   // Since we know just one rider in our graph rides for team Yamaha,
   // we can also write this and only get the first record:
   let (name, birth_year): (String, u32) = graph.query("MATCH (r:Rider)-[:rides]->(t:Team) WHERE t.name = 'Yamaha' RETURN r.name, r.birth_year")?;
   // Let's now get all the data about the riders we have.
   // Be aware of that we only know the height of some riders, and therefore we use an `Option`:
   let results: Vec<(String, u32, Option<f32>)> = graph.query("MATCH (r:Rider) RETURN r.name, r.birth_year, r.height")?;

   // That was just a demo; we don't need this graph anymore. Let's delete it from the database:
   //graph.delete()?;

   Ok(())

Step 6. Run the current local package#

 cargo run

Step 7. Monitor the Graph query#

 1633515550.109594 [0 172.17.0.1:55114] "GRAPH.QUERY" "MotoGP" "CREATE (dummy:__DUMMY_LABEL__)" "--compact"
 1633515550.111727 [0 172.17.0.1:55114] "GRAPH.QUERY" "MotoGP" "MATCH (dummy:__DUMMY_LABEL__) DELETE dummy" "--compact"
 1633515550.114948 [0 172.17.0.1:55114] "GRAPH.QUERY" "MotoGP" "CREATE (:Rider {name: 'Valentino Rossi', birth_year: 1979})-[:rides]->(:Team {name: 'Yamaha'}), (:Rider {name:'Dani Pedrosa', birth_year: 1985, height: 1.58})-[:rides]->(:Team {name: 'Honda'}), (:Rider {name:'Andrea Dovizioso', birth_year: 1986, height: 1.67})-[:rides]->(:Team {name: 'Ducati'})" "--compact"
 1633515550.118380 [0 172.17.0.1:55114] "GRAPH.QUERY" "MotoGP" "MATCH (r:Rider)-[:rides]->(t:Team) WHERE t.name = 'Yamaha' RETURN r.name, r.birth_year" "--compact"
 1633515550.120766 [0 172.17.0.1:55114] "GRAPH.QUERY" "MotoGP" "MATCH (r:Rider)-[:rides]->(t:Team) WHERE t.name = 'Yamaha' RETURN r.name, r.birth_year" "--compact"
 1633515550.122505 [0 172.17.0.1:55114] "GRAPH.QUERY" "MotoGP" "MATCH (r:Rider) RETURN r.name, r.birth_year, r.height" "--compact"
 1633515550.124045 [0 172.17.0.1:55114] "GRAPH.DELETE" "MotoGP"

Step 8. Install RedisInsight#

For this demo, we will be using RedisInsight Docker container as shown below:

 docker run -d -v redisinsight:/db -p 8001:8001 redislabs/redisinsight:latest

Step 9. Accessing RedisInsight#

Next, point your browser to http://localhost:8001.

Step 10. Run the Graph Query#

You can use the limit clause to limit the number of records returned by a query:

 GRAPH.QUERY "MotoGP" "MATCH (r:Rider) RETURN r.name, r.birth_year, r.height"

References#

  • Learn more about RedisGraph in the Quickstart tutorial.

Please hit your text content and then hit enter.