圆点 快捷的未来即将来到你所在的城市。

加入我们,参加 Redis 发布会

多模型实战:同时使用 RedisGraph 和 RediSearch

在 RedisConf19 上,我演示了一个在 RedisGraph 中的节点上运行 RediSearch 全文搜索的解决方案。活动前那段时光有些模糊,但现在几周后,我意识到我们应该更详细地解释我们是如何做到这一点的,并发布源代码。

在此演示中,我展示了一个小接口,允许你搜索动物,并通过生物分类系统(界、门、纲、目等)了解它们的关联性。全文部分基于维基百科中的第一个英文段落。因此,作为一个例子,假设你搜索“猫家宠物”(家猫,Felis catus)和“须鲸蓝”(蓝鲸,Balaenoptera musculus),你将看到它们都仅仅是哺乳动物,而如果你搜索“猫家宠物”和“雪中亚猫”(雪豹,Panthera uncia ),你将看到它们都属于同一科,猫科。

这个演示项目出人意料的简单,但我要指出的是,RediSearch 和 RedisGraph 之间的集成仍处于早期阶段,在撰写本文时还没有准备好进行生产。我鼓励你弄清楚这种方法是否能够满足你的需求,并且要明白 RediSearch 和 RedisGraph 之间的集成将在未来几个月内成熟和扩展。

与此同时,我们来聊聊这个演示的组件。首先要完成的事情 是基于仓库中的正确分支构建 RediSearch 和 RedisGraph。对于 RediSearch,那仅仅是当前主分支,而对于 RedisGraph,你需要redisconf 分支。如果你想为了你自己的需求复制这个解决方案,那么你需要从头构建这两个模块。RedisGraph 的网站RediSearch 都有详细的说明,讲解如何执行此操作,这需要花费一点时间,但不难。

在你的 redis.conf 文件中,你需要确保 RedisGraph 在 RediSearch 之前加载。为此,转到 redis.conf 文件,并在模块部分,将 RediSearch 的 loadmodule 指令放在 RedisGraph 之前。这样,当 RedisGraph 加载时,它将检测到搜索模块的存在。在你完成编辑 redis.conf 后,你可以继续并重启 Redis 服务。

演示 repo中,我已将数据集整合在一起,使用redisgraph-bulk-loader脚本,将以下内容从 CSV 加载到 RedisGraph 中。该数据集仅包括动物界中的哺乳动物,这是因为哺乳动物之外的动物可用的数据质量较低(非哺乳动物物种很少有好的维基百科描述)。

以下是数据加载方式

$ cd redisgraph-bulk-loader/
$ python3 bulk_insert.py MAMMALS -q -n /path/to/demo/dataload/Class.csv -n /path/to/demo/dataload/Family.csv -n /path/to/demo/dataload/Genus.csv -n /path/to/demo/dataload/Order.csv -n /path/to/demo/dataload/Species.csv -r /path/to/demo/dataload/IN_CLASS.csv -r /path/to/demo/dataload/IN_FAMILY.csv -r /path/to/demo/dataload/IN_GENUS.csv -r /path/to/demo/dataload/IN_ORDER.csv -a yourpassword
创建了 1 个带有标签“Class”的节点
创建了 157 个带有标签“Family”的节点
创建了 1272 个带有标签“Genus”的节点
创建了 29 个带有标签“Order”的节点
使用标签“物种”创建了 5616 个节点
为类型“IN_CLASS”创建了 29 个关系
为类型“IN_FAMILY”创建了 1272 个关系
为类型“IN_GENUS”创建了 5616 个关系
为类型“IN_ORDER”创建了 157 个关系
图“MAMMALS”构建完成:在 0.443749 秒内创建了 7075 个节点和 7074 个关系
$ redis-cli -a yourpassword GRAPH.QUERY MAMMALS "CALL db.idx.fulltext.createNodeIndex('Species','description')"
警告:在命令行界面中使用“-a”或“-u”选项和密码可能不安全。
1) (空列表或集合)
2) (空列表或集合)
3) 1) “查询内部执行时间:324.970000 毫秒”

(gist:https://gist.github.com/stockholmux/0727a4a784a46f8cb9e8329d393a513a)

此时,键 MAMMALS 包含我们的整个图。一些重要提示

  • bulk_insert.py 上的 -q 开关非常重要,因为它允许在读取 CSV 时采用智能引用。
  •  redis-cli 调用一次对所有节点进行批量索引,因此实际上它要吸收超过 7,000 份全文搜索文档。

现在,让我们启动并运行 UI。与几乎任何 Node.js 应用程序一样,我们从 npm install 开始。这可能需要几秒钟,因为我们不仅管理着 Node.js 的服务器端文件,还管理着前端 Vue.js 组件。如果您最近没有在前端 Javascript 世界中花费太多时间,那么它不再是 FTP 和 HTML 文件事务。现代前端开发者非常重视他们的工具,因此我们需要安装 Vue CLI(我建议按照 Vue CLI 快速入门指南)。

安装前端工具后,让我们返回 npm 并通过运行构建前端

$ npm run build

这将创建 dist 目录,我们将从该目录提供所有前端文件。现在我们已经在 Redis 中有了数据,前端文件已经可以提供服务,因此我们可以启动服务器

$ node server.js -p 6379 -a yourpassword -h yourhostOrlocalhost

让我们暂停一下,介绍几个关于我们刚刚启动的服务器的信息。它建立在 Express.js 的基础上,主要使用 websocket 进行来回通信。我还集成了 Visible Engine 调试工具,它允许你查看在其他浏览器窗口中执行的命令。你可以通过将浏览器指向 http://localhost:4444 来试用该演示。

总而言之,它对于它的用途来说非常简洁——只有 75 行代码。我们的解决方案不需要这么长,因为我们真正要做的只是接受 websocket 连接、根据所传递的消息运行 Redis 命令以及将这些消息和结果重新传递回去。Redis(Graph) 负责这里所有的繁重工作。让我们看看我们正在执行的命令。

要搜索关键词,我们会运行此命令

> GRAPH.QUERY MAMMALS "CALL db.idx.fulltext.queryNodes('Species','cat house pet')"

这个相当不复杂。我们的密码是 MAMMALS,我们使用特殊的 Cypher 语法调用特定函数,传递我们正在寻找的节点的标签和实际搜索字符串。您可以传递有效的 RediSearch 查询,但请记住,这目前只是全文搜索,因此请不要使用地理空间、标签或数字子句。

一旦我们确定了我们要比较的两种动物,我们将使用直接的 Cypher 查询

> GRAPH.QUERY MAMMALS "MATCH (s:Species)-[*]->(x)<-[*]-(c:Species) WHERE c.fullname = 'Felis catus' AND s.fullname = 'Balaenoptera borealis'  RETURN x.name, labels(x) LIMIT 1"

server.js 文件中,这些查询被表示为 Javascript 模板字符串。没有隐藏内容,只是将用户输入通过字符串插值传递给查询。但是,如果在生产环境中部署此类查询,您需要小心接受用户输入。

如果您计划修改前端代码,请务必编辑 /src 目录,而不是 /dist 目录。编辑后,您需要再次运行 npm run build 或使用开发服务器 (npm run serve),它会自动编译对前端代码的更改并在另一个端口上提供服务。同样,这里没有太多内容,它是一个标准的 Vue.js 和 Bootstrap 应用程序。唯一真正相关的文件是 /src/App.js, /src/components/panels.vue/src/components/search.vue

就这样了。一个简单的演示来展示一个强大的功能,该功能集成了两个不同的模型 - 图和全文搜索。我鼓励您玩一下演示并提交自己的数据集。