【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试试看。

スクリーンショット 2019-01-26 0.20.31.png

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

スクリーンショット 2019-01-26 1.11.04.png

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

スクリーンショット 2019-01-26 1.29.32.png

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

スクリーンショット 2019-01-26 1.31.33.png

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

スクリーンショット 2019-01-26 1.16.39.png

最后

我成功创建了能够添加和引用「用户」和「文章」数据的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实现要点

bannerAds