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 实作,就可能有几种做法
有注意到上面的粗体字吗?如果我们用 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 来表达特别强大呢!
相较於 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 3.5 或以前的版本,有个 GraphQL plugin 可以直接操作查询 Neo4j 资料库,如图
(请注意 Neo4j 4.0 不支援 GraphQL plugin,这个 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 查询之前,得先上传 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")
}
')
上传 GraphQL schema 後,确定一下目前的 Schema
call graphql.schema()
接着就可以开始用 GraphQL 查询 Neo4jDB
{ Person(name:"Kevin Bacon") {
name
born
movies {
title
released
tagline
}
}
}
GraphQL plugin 还可以进行许多进阶查询或修改资料,但 Neo4j 官方已不再支援维护,所以打算先体验到这里即可,之後再看看其他 GraphQL 的解决方案~
参考资源
https://github.com/neo4j-graphql/neo4j-graphql
https://grandstack.io/docs/neo4j-graphql-database-plugin/
量化交易30天 本系列文章是纪录一位量化交易新手的学习过程,除了基础的Python语法不说明,其他...
制作样板 昨天已经绘制出每个淡绿色的点来显示资料中的经纬度在svg地图上面,今天要做的事情是当滑鼠移...
前言 前篇教学已经能让 Google 搜寻到网站,接下来若想做流量分析的话,需要埋 Google A...
今天我们要来学习如何把Sass切分支许多档案 这样会使我们比较容易管理 @import(汇入) 可将...
今天来看一下如何使用Shioaji问回历史交易资料,不过在此先提醒一下,上一篇有讲到的永丰讲师的Yo...