学习

如何使用 Rust 查询 Redis 中的图形数据

Ajeet Raina
作者
Ajeet Raina Redis 前开发者增长经理
停产通知

Redis 正在逐步淘汰 RedisGraph。 这篇博文 解释了这一决定背后的动机,以及对现有 Redis 客户和社区成员的影响。

计划于 2025 年 1 月 31 日终止支持。

RedisGraph 是第一个可查询的属性图数据库,它使用稀疏矩阵来表示图中的邻接矩阵,并使用线性代数来查询图。RedisGraph 基于一种独特的方法和架构,将 Cypher 查询转换为在 GraphBLAS 引擎上执行的矩阵运算。这种新设计使社交图操作、欺诈检测和实时推荐等用例的执行速度比任何其他图数据库快 10 到 600 倍。毫无疑问,它是处理实时复杂图操作最快的图数据库,比任何其他图数据库快 10 到 600 倍。它主要通过多个可视化集成(包括 RedisInsight、Linkurious 和 Graphileon)展示您的数据是如何连接的。

RedisGraph 是一个在 Redis 之上从头开始开发的图数据库,它使用新的 Redis 模块 API 来扩展 Redis 的新命令和功能。其主要特点包括:使用内存高效的自定义数据结构,对存储在 RAM 中的数据进行简单、快速的索引和查询。Redis Graph 是一个有向图,其中节点和关系都是有类型的 - 节点带有标签,边带有类型。节点和边可以并且通常包含属性,如 SQL 数据库中的列或文档存储中的键。更新的 RedisGraph 2.0 基准测试显示,在执行图遍历时,并行工作负载(多个客户端)的延迟改进了 6 倍,吞吐量改进了 5 倍。

以下是 RedisGraph 的主要用例

  • 推荐:它允许您通过检查客户与他们想要的体验之间的关系,快速找到他们之间的联系。
  • 图形辅助搜索:它允许您搜索单个或多个单词或短语,并在图形结构上实时执行全文和语言查询和实现。
  • 身份和访问管理:它允许您将复杂的资源访问权限定义为一个图形,并使用单个查询实现对这些权限的快速实时验证。

RedisGraph Rust 客户端#

Rust 编程语言速度极快且内存效率高:它没有运行时或垃圾收集器,可以为性能至关重要的服务提供支持,在嵌入式设备上运行,并且可以轻松地与其他语言集成。它是一个最初由 Mozilla Research 开发的开源项目。Rust 库是可移植 Rust 软件的基础,是更广泛的 Rust 生态系统中一组经过实战检验的最小共享抽象。

redisgraph-rs 是 RedisGraph(Redis 的图数据库)的惯用 Rust 客户端。这个 crate 解析来自 RedisGraph 的响应,并将它们转换为普通的 Rust 值。它提供了一个非常灵活的 API,允许您只使用一个函数检索单个值、单个记录或多个记录:Graph::query。

按照以下步骤开始使用 Rust 的 RedisGraph

步骤 1. 运行 Redis Stack Docker 容器#

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

步骤 2. 验证是否已加载 RedisGraph 模块#

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

步骤 3. 安装 Rust#

 brew install rust

步骤 4. 克隆存储库#

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

步骤 5. 编写 Rust 程序#

复制以下内容并将其保存为 src 目录下的 "main.rs"。

 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(())

步骤 6. 运行当前本地包#

 cargo run

步骤 7. 监控图形查询#

 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"

步骤 8. 安装 RedisInsight#

在本演示中,我们将使用 RedisInsight Docker 容器,如下所示

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

步骤 9. 访问 RedisInsight#

接下来,在浏览器中访问 https://localhost:8001。

步骤 10. 运行图形查询#

您可以使用 limit 子句来限制查询返回的记录数

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

参考资料#

请点击您的文本内容,然后按回车键。