【GraphQL】在30分钟内开发了可以与Neo4j进行交互的GraphQL
首先
在中文中,我們經常看到關於GraphQL針對著名關聯式資料庫(如MySQL)的解說,但針對圖形資料庫的文章相對較少。這次我們將以Node.js為例,在30分鐘內實現使用GraphQL操縱Neo4j的程式。
假设您了解Neo4j和GraphQL是什么,下面将进行解释,请先使用谷歌搜索引擎了解一下。
※Neo4j是最受欢迎的开源图形数据库。
请解释条件。
我能够在本地环境中运行Neo4j。我了解GraphQL和Neo4j的基本使用方法。
打造环境
在Neo4j中引入APOC插件。
APOC是Neo4j的扩展库,它增加了在Cypher中可用的表达式。它用于在使用GraphQL更新数据时。
在Neo4j官方网站上有关于如何安装的说明。
APOC用户指南3.4.0.4
学习并掌握ES6使您能够流利地编写Javascript。
首先,创建一个名为neo4j-graphql-sample的文件夹。
为了将import等ES6的Javascript代码转译成可在Node.js中执行的代码,我们需要引入babel。
请详细阅读这篇文章。
$ mkdir neo4j-graphql-sample
$ cd neo4j-graphql-sample
$ npm init -y
$ npm install --save-dev babel-cli babel-preset-env
创建 .babelrc 文件。
{
"presets": [
[
"env", {
"targets": {
"node": "current"
}
}
]
]
}
更改 package.json 文件。
{
...
"scripts": {
"start": "babel-node index.js"
},
...
}
安装GraphQL实现所需的库。
使用Apollo这个库来实现GraphQL。
通过使用Apollo,可以轻松地将GraphQL服务器与前端连接起来。现在,讨论GraphQL实现实际上已经变成讨论Apollo服务器实现的话题,因为它是如此受欢迎的库。
另外,为了操作neo4j,我们将使用neo4j-driver和neo4j-graphql-js这两个工具。
$ npm install --save apollo-server-express \
apollo-errors \
express \
cors \
graphql \
graphql-tag \
graphql-tools \
neo4j-driver \
neo4j-graphql-js
创建GraphQL
在实现GraphQL时的要点是,首先定义查询的类型模式(schema),然后创建返回数据的解析器(resolver),并准备用于与Neo4j进行数据交互的驱动程序,并将其配置到Apollo服务器中。
Apollo服务器将使用express进行构建。
那么,我们来创建index.js并开始编写实际的代码。
import { makeAugmentedSchema } from 'neo4j-graphql-js'
import { ApolloServer } from 'apollo-server-express'
import express from 'express'
import bodyParser from 'body-parser'
import cors from 'cors'
import { v1 as neo4j } from 'neo4j-driver'
import { typeDefs, resolvers } from './schema'
// スキーマの作成
// typeDefsにQueryとMutationの型を定義する
const schema = makeAugmentedSchema({
typeDefs,
config: {
query: true,
mutation: false
}
})
const neo4jUri = process.env.NEO4J_URI || 'bolt://localhost:7687'
const neo4jUser = process.env.NEO4J_USER || 'neo4j'
const neo4jPassword = process.env.NEO4J_PASSWORD || 'neo4j'
// ドライバーの作成
const driver = neo4j.driver(neo4jUri, neo4j.auth.basic(neo4jUser, neo4jPassword))
// expressサーバーの作成
const app = express()
app.use(bodyParser.json())
app.use(cors())
const playgroundEndpoint = '/graphql'
// Apolloサーバーの作成
// playgroundは試しにクエリを流せるエディタ、後で使用する
const server = new ApolloServer({
schema,
resolvers,
context: ({ req }) => {
return {
driver,
req,
}
},
introspection: true,
playground: {
endpoint: playgroundEndpoint,
settings: {
'editor.theme': 'light'
}
}
})
// expressとapolloサーバーを繋げる
server.applyMiddleware({ app, path: '/' })
app.listen(4000, () => {
console.log(`http://localhost:4000/graphql`)
})
我将创建一个schema.js文件。
在schema.js中定义了模式的类型和解析器。
在模式中,可以使用@relation和@cypher指令。@relation可以定义Neo4j节点之间的边缘连接,而@cypher可以直接在Neo4j中执行Cypher查询。
使用Resolver根据模式创建返回数据。
通过使用neo4jgraphql,Resolver将自动判断是Query还是Mutation,并在进行数据库操作后创建返回数据。
這次我們將添加「User」和「Article」作為節點,並添加「WRITE」作為邊,創建可以查詢和修改的型別。
import { neo4jgraphql } from 'neo4j-graphql-js'
export const typeDefs = `
type Article {
_id: ID
uuid: ID!
title: String!
description: String!
created_at: Date!
write_user: User @relation(name: "WRITE", direction: "IN")
}
type User {
_id: ID
uuid: ID!
name: String!
created_at: Date!
write_articles: [Article] @relation(name: "WRITE", direction: "OUT")
}
type Query {
Article(_id: ID, title: String, description: String, created_at: Date): [Article]
User(_id: ID, uid: ID, name: String, avatar: String, created_at: Int): [User]
}
type Mutation {
writeArticle(title: String!, description: String! user_uuid: ID!): Article
@cypher(statement:"MATCH (u:User {uuid: $user_uuid}) MERGE (u)-[r:WRITE]->(n:Article {uuid: apoc.create.uuid(), title: $title, description: $description, created_at: apoc.date.format(apoc.date.add(timestamp(), 'ms', 9, 'h'), 'ms')}) return n")
createUser(name: String!): User
@cypher(statement:"CREATE (n:User {uuid: apoc.create.uuid(), name: $name, created_at: apoc.date.format(apoc.date.add(timestamp(), 'ms', 9, 'h'), 'ms')}) return n")
}
`
export const resolvers = {
Query: {
Article(obj, args, ctx, info) {
return neo4jgraphql(obj, args, ctx, info)
},
User(obj, args, ctx, info) {
return neo4jgraphql(obj, args, ctx, info)
},
},
Mutation: {
writeArticle(obj, args, ctx, info) {
return neo4jgraphql(obj, args, ctx, info)
},
createUser(obj, args, ctx, info) {
return neo4jgraphql(obj, args, ctx, info)
},
}
}
在Playground中尝试使用GraphQL。
让我们启动Neo4j,并使用npm start来运行刚才实现的Apollo服务器。
$ npm start
> neo4j-graphql-sample@1.0.0 start ~/neo4j-graphql-sample
> babel-node index.js
http://localhost:4000/graphql
当成功启动Apollo服务器时,您可以通过访问localhost:4000/graphql来打开一个名为Playground的编辑器,从而在浏览器上测试GraphQL查询。
如果你不知道如何编写GraphQL查询,请在下面的链接中简要学习。
我整理了关于GraphQL查询的基础知识。
让我们在createUser的Mutation中添加一个新的User试试看。

让我们尝试在writeArticle的Mutation中添加一篇文章。
将在执行createUser时获取的User的uuid放入user_uuid并执行。

让我们在文章的查询中参考一下。

顺便提一下,当运行以下查询时,还可以参考写文章的用户信息。

目前,Neo4j中應該已經註冊了「User」和「Article」作為節點,以及「WRITE」作為邊緣。請使用瀏覽器訪問Neo4j編輯器進行確認。

最后
我成功创建了能够添加和引用「用户」和「文章」数据的GraphQL。
我已经将示例代码上传到GitHub上了。
请将以下内容用中文进行表述,只需一种版本:
https://github.com/kousaku-maron/neo4j-graphql-sample
这是一个指向kousaku-maron/neo4j-graphql-sample GitHub存储库的链接。
如果您不需要自动添加边缘的“WRITE”,那么您可以将makeAugmentedSchema的config中的mutation设置为true,就可以自动使用Mutation,而无需自己创建。
这里还写了一篇整理了认证和授权以及GraphQL实现时需要考虑的问题的文章,请随便看看。
【GraphQL】需要重点关注的GraphQL实现要点