学习

如何使用 .NET 在 Redis 中查询图数据

Ajeet Raina
作者
Ajeet Raina, Redis 前开发者增长经理
生命周期结束通知

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

计划于 2025 年 1 月 31 日结束支持。

RedisGraph 使您能够使用 [Cypher 查询语言](https://opencypher.org/) 在 Redis 中存储和查询图数据。在本文中,我们将讨论 RedisGraph 在 .NET 中的用法。

NRedisGraph#

在本教程中,我们将使用 NRedisGraph 包。要在您的项目中安装该包,请使用 dotnet add package NRedisGraph

运行 RedisGraph#

在本地快速启动并运行 RedisGraph 的最简单方法是使用 RedisGraph docker 镜像

docker run -p 6379:6379 redis/redis-stack-server:latest

上述命令将在本地启动一个加载了 RedisGraph 模块的 Redis 实例,您可以通过 localhost:6379 连接到它。

连接#

NRedisGraph 利用了与 NRedisGraph 一起安装的 StackExchange.Redis 项目。要创建 RedisGraph 对象,您首先需要创建一个 ConnectionMultiplexer,从中获取一个 IDatabase 对象的引用,然后用该 IDatabase 对象初始化 RedisGraph

var muxer = ConnectionMultiplexer.Connect("localhost");
var db = muxer.GetDatabase();
var graph = new RedisGraph(db);

发送查询#

RedisGraph 中的查询适用于广泛的操作,但从根本上讲,使用 NRedisGraph 执行查询时,您只需执行 graph.Querygraph.QueryAsync,并传入您要查询的图的名称和要运行的查询即可。例如,在本教程的其余部分,我们将使用 pets 图,pets 是存储图的键的名称。因此,对 graph.Querygraph.QueryAsync 的任何调用都将首先传入 pets 以指示要操作的图。

创建节点#

要在 RedisGraph 中创建节点,您将使用 Create 操作。让我们先创建 2 个人类节点:Alice 和 Bob。

var createBobResult = await graph.QueryAsync("pets", "CREATE(:human{name:'Bob',age:32})");
await graph.QueryAsync("pets", "CREATE(:human{name:'Alice',age:30})");

对 RedisGraph 运行查询将产生一个 ResultSet。此结果将在 Statistics 部分包含有关查询结果的一些元数据以及查询生成的任何结果。在上述情况下,唯一返回的是查询的统计信息,您可以直接从结果对象中打印出来。

Console.WriteLine($"Nodes Created:{createBobResult.Statistics.NodesCreated}");
Console.WriteLine($"Properties Set:{createBobResult.Statistics.PropertiesSet}");
Console.WriteLine($"Labels Created:{createBobResult.Statistics.LabelsAdded}");
Console.WriteLine($"Operation took:{createBobResult.Statistics.QueryInternalExecutionTime}");

只需执行另一个 CREATE 语句,您就可以创建带有其他标签的节点。例如,如果我们想创建一个名为 'Honey'、5 岁的灵缇犬 'pet',我们将运行

await graph.QueryAsync("pets", "CREATE(:pet{name:'Honey',age:5,species:'canine',breed:'Greyhound'})");

创建关系#

与创建节点类似,您也可以使用 Query/QueryAsync 命令在 RedisGraph 中创建关系。例如,要在 Bob 和灵缇犬 Honey 之间建立 OWNER 关系,您可以使用以下命令:

await graph.QueryAsync("pets",
    "MATCH(a:human),(p:pet) WHERE(a.name='Bob' and p.name='Honey') CREATE (a)-[:OWNS]->(p)");

查询关系#

现在我们已经在节点之间创建了一些节点和关系,我们可以再次使用 QueryQueryAsync 在图中查询数据。因此,例如,如果我们想找到 Honey 的所有所有者,我们将发出以下查询

var matches = await graph.QueryAsync("pets", "MATCH(a:human),(p:pet) where (a)-[:OWNS]->(p) and p.name='Honey' return a");

然后我们可以遍历结果匹配项,这是与之前使用的相同的 ResultSet 类,但这次它将包含我们可以访问的实际结果。

foreach (var match in matches)
{
    Console.WriteLine(((Node) match.Values.First()).PropertyMap["name"].Value);
}

我们还可以通过查找所有与 Honey 存在 WALKS 关系的人来找到 Honey 的所有遛狗者:

matches = await graph.QueryAsync("pets", "MATCH(a:human),(p:pet) where (a)-[:WALKS]->(p) and p.name='Honey' return a");

然后,如果我们想找到 Bob 的所有狗,我们可以查询图,找到所有与名叫 Bob 的人存在 OWNS 关系的犬类。

matches = await graph.QueryAsync("pets", "MATCH(a:human),(p:pet) where (a)-[:OWNS]->(p) and p.species='canine' and a.name='Bob' return p");

资源#

  • 此演示的代码可在 GitHub 上获取
  • 要了解更多关于 RedisGraph 的信息,请查阅 文档网站
  • 要了解更多关于 Cypher 查询语言的信息,请访问 opencypher.org