以 GraphQL 查询 Neo4j 资料库

前言

GraphQL 与 Neo4j

GraphQL 原是 Facebook 内部的开发计画,现已独立出来成为 GraphQL 基金会。相较於 RESTful API,GraphQL 前端应用可以自定义每次查询时,仅需要的部分资料栏位和范围,後端也只需要回传一小部分资料,藉此让资料存取更有弹性、灵活和高效率。

GraphQL 的出现,并不是为了完全取代 REST,目前各式应用服务仍以 RESTful API 为最大宗,但是在前後端的资料存取组合愈趋复杂与多变时,RESTful API 便会不敷使用。

举例来说,假设有一支 API 可以取得使用者的留言,那麽这就可以是一支 RESTful API。再来,除了留言本身图文资料,我还想要看到有哪些人对它按赞(User LIKE Comment)、有哪些人分享了这则留言(User Share Comment)、有哪些人回覆了这一则留言(User Reply Comment)、以及这些回覆的留言内容(User Write Comment Reply Comment),以上的需求,如果要以 RESTful API 实作,就可能有几种做法

  • 实作多支 API 来取得不同程度/深度的资料,API 职责分明
    但前端会需要为了一个需求,和後端互动多次,额外浪费许多连线与资料传输的时间
  • 只提供一支 API 让前端呼叫,并提供参数化的查询
    後端会需要在单一查询中 JOIN 多个资料表,进行复杂的资料组合和运算,效率不佳。且为了在单一要求中保留前端应用的弹性,这支 API 会回传大部分的栏位,即使前端根本不需要,这造成资料传输的浪费

有注意到上面的粗体字吗?如果我们用 Cypher 语法来表达,就变成了

(u:User)-[:LIKE]->(c:Comment)
(u:User)-[:Share]->(c:Comment)
(u:User)-[:Reply]->(c:Comment)
(u:User)-[:Write]->(r:Comment)-[:Reply]->(c:Comment)

是不是觉得在这种多层次的复杂查询应用上,用 Graph 来表达特别强大呢!

GraphQL 与 GraphDB

相较於 Cypher 是 Neo4j 资料库的专属查询语言,GraphQL 则是开放性的查询语言,其後端可以是关联式资料库。然而从上述的范例,应该隐约可以感受到,GraphQL + GraphDB 应该会是天作之合吧!

概念上来说,以之前的电影资料库为例,以 Cypher 查询某一部电影的演员如下

MATCH (m:Movie { title: 'The Matrix' })<-[:ACTION]-(p:Person)
RETURN m, p

以 GraphQL 来表达大概像是这样

query {
   Movie(title:"The Matrix") {
      title
      released
      tagline
      actors {
         name
         born
      }
   }
}

对应的查询结果

{
   "Movie": [{
      "title": "The Matrix",
      "released": 1999,
      "tagline": "Welcome to the Real World",
      "actors": [{
         "name": "Keanu Reeves",
         "born": 1964
         }, {
         "name": "Carrie-Anne Moss",
         "born": 1967
         }, {
         "name": "Laurence Fishburne",
         "born": 1961
         }
      ]
   }]
}

从上述语法可以看出,GraphQL 可以非常弹性且直觉的操作 GraphDB,且客制化回传的做资料范围。

安装 Neo4j GraphQL plugin

如果你使用的是 Neo4j 3.5 或以前的版本,有个 GraphQL plugin 可以直接操作查询 Neo4j 资料库,如图
(请注意 Neo4j 4.0 不支援 GraphQL plugin,这个 plugin 之後也不会再继续维护和升级)

Neo4j GraphQL plugin

Neo4j Server 版的话,就是直接把下载的 jar 档案复制到 plugins 资料夹底下,并重新启动 Neo4j 即可
因为我想体验一下 GraphQL plugin,所以用 Docker 的方式跑旧版的 Neo4j

docker run \
    --name egg_neo4j_3.5 \
    -p7474:7474 -p7687:7687 \
    -d --env NEO4J_AUTH=neo4j/mypassword \
    neo4j:3.5

docker cp neo4j-graphql-3.5.21.5.jar egg_neo4j_3.5:/var/lib/neo4j/plugins/

此外,还要修改 neo4j.conf

dbms.unmanaged_extension_classes=org.neo4j.graphql=/graphql

或是在上述的 docker run 指令加上参数

--env NEO4J_dbms_unmanaged__extension__classes=org.neo4j.graphql=/graphql

Neo4j 服务启动後,记得在 browser 重新产生资料库

:play movie graph

设定 GraphQL Schema

在操作 GraphQL 查询之前,得先上传 GraphQL Schema,有两种做法
先假设我们的 Schema 如下

type Movie  {
  title: String!
  released: Int
  actors: [Person] @relation(name:"ACTED_IN",direction:IN)
}
type Person {
  name: String!
  born: Int
  movies: [Movie] @relation(name:"ACTED_IN")
}

第一种做法是在 GraphiQL POST http://localhost:7474/graphql/idl 并输入上述的 Schema 内容,如果有设定密码,记得也是要设定 HTTP Authorization Header
第二种做法是打开 Neo4j browser,呼叫预存程序 graphql.idl

CALL graphql.idl('
    type Movie  {
      title: String!
      released: Int
      tagline: String
      actors: [Person] @relation(name:"ACTED_IN",direction:IN)
    }
    type Person {
      name: String!
      born: Int
      movies: [Movie] @relation(name:"ACTED_IN")
    }
')

Neo4j GraphQL Change Schema

上传 GraphQL schema 後,确定一下目前的 Schema

call graphql.schema()

Neo4j GraphQL Schema

接着就可以开始用 GraphQL 查询 Neo4jDB

{ Person(name:"Kevin Bacon") {
    name
    born
    movies {
      title
      released
      tagline
    }
  }
}

Neo4j GraphiQL sample

GraphQL plugin 还可以进行许多进阶查询或修改资料,但 Neo4j 官方已不再支援维护,所以打算先体验到这里即可,之後再看看其他 GraphQL 的解决方案~

参考资源

https://github.com/neo4j-graphql/neo4j-graphql
https://grandstack.io/docs/neo4j-graphql-database-plugin/


<<:  Day 28. F2E-过渡动画

>>:  Day 29 - 使用 AWS S3 服务

量化交易30天 Day30 - 量化交易 v.s. 主观交易

量化交易30天 本系列文章是纪录一位量化交易新手的学习过程,除了基础的Python语法不说明,其他...

D3JsDay19 地图加入了事件,地点资料就呈现—为地图加入互动事件

制作样板 昨天已经绘制出每个淡绿色的点来显示资料中的经纬度在svg地图上面,今天要做的事情是当滑鼠移...

Day28 - 如何埋 GA (Google Analytics)

前言 前篇教学已经能让 Google 搜寻到网站,接下来若想做流量分析的话,需要埋 Google A...

Sass @import DAY34

今天我们要来学习如何把Sass切分支许多档案 这样会使我们比较容易管理 @import(汇入) 可将...

Day29 - [Shioaji] 超入门!永丰证券程序交易API快速上手 (2)

今天来看一下如何使用Shioaji问回历史交易资料,不过在此先提醒一下,上一篇有讲到的永丰讲师的Yo...