neo4j结合graphql,解读第一个例子migration
发布于 作者:苏南大叔 来源:程序如此灵动~在实际的graphql
应用中,apollo server
在某种意义上成了graphql
的代名词。在neo4j
+graphql
的官方例子中,第一个例子migration
就是基于apollo server
的代码实现。在本文中,苏南大叔将对这个例子做初步的解读。
大家好,这里是苏南大叔的程序如此灵动博客,这里记录苏南大叔和计算机代码的故事。本文描述如何基于apollo server
和neo4j
,实现graphql
接口。测试环境:@neo4j/graphql@3.12.0
,neo4j-driver@5.1.0
,apollo-server@3.10.3
,neo4j@4.4.10
,node@16.14.2
。
测试代码
本文的测试代码来自于下面的网址:
下载回来后,使用yarn install
安装相关依赖,然后执行npm start
或者yarn start
,打开apollo server
的接口检测界面,如下图所示:
apollo server
的使用过程,可以参考下面这篇文章:
代码解读之主体框架
这个example
的migration
代码非常简单,主要分为以下几个部分(为了叙述方便,对代码略有修改):
主体代码index.js
:
const neo4j = require("neo4j-driver");
const { ApolloServer } = require("apollo-server");
const { Neo4jGraphQL } = require("@neo4j/graphql");
const typeDefs = require("./typeDefs");
const driver = neo4j.driver("bolt://localhost:7687", neo4j.auth.basic("neo4j", "neo4j"));
const neo4jGraphQL = new Neo4jGraphQL({ typeDefs, driver });
neo4jGraphQL.getSchema().then((schema) => {
const server = new ApolloServer({
schema,
context: ({ req }) => ({ req })
});
server.listen().then(({ url }) => {
console.log(`GraphQL server ready at ${url}`);
});
});
这个代码几乎是不要修改的,只需要修改其中的neo4j
的配置地址、用户名、密码部分。
const driver = neo4j.driver("bolt://localhost:7687", neo4j.auth.basic("neo4j", "neo4j"));
代码解读之结构定义
gql
定义typeDefs.js
:
const { gql } = require("apollo-server");
const typeDefs = gql`
type Movie {
title: String!
reviews: [Review!]! @relationship(type: "HAS_REVIEW", direction: OUT)
averageRating: Float!
@cypher(
statement: """
MATCH (this)-[:HAS_REVIEW]->(r:Review)
RETURN avg(r.rating)
"""
)
}
type Review {
id: ID! @id
rating: Float!
createdAt: DateTime!
content: String!
author: User! @relationship(type: "AUTHORED", direction: IN)
movie: Movie! @relationship(type: "HAS_REVIEW", direction: IN)
}
type User {
username: String!
reviews: [Review!]! @relationship(type: "AUTHORED", direction: OUT)
}
`;
module.exports = typeDefs;
这里的代码非常重要,主要定义了数据库结构,这部分代码将影响最终的接口的实现。根据以前的文章,apollo server
包括两个部分,分别是:typeDefs
和resolvers
。在本文中,typeDefs
是自定义的,而resolvers
是自动生成的。
这个typeDefs
中,感叹号是表示"必选"。而@relationship
则可以理解为outer join
,就是外联查询。
转换为neo4j
代码
这里有两个既定的结论,可能和大家的习惯概念理解不同:
- 实际上
neo4j
的配置信息错误的话,依然不影响这个graphql
接口的生成,只不过执行接口的时候会报错而已。 neo4j
数据库里面可以不用内置任何节点信息和数据,graphql
接口正确执行neo4j
语句接口,就可以创造一切数据。
可能需要的清库代码【执行前,请清楚认知自己在干什么!】如下,参考文章:
match (n) detach delete n
为了表述逻辑的需要,根据上一个步骤中结构gql
定义的内容,苏南大叔生成了一些neo4j
语句,可以在neo4j browser
中执行,以获得一些目标数据。gql
定义中的direction
为out
的关系是暂时不用考虑的,direction
为in
的关系将体现在下面的构建语句中。
merge (u:User{username:'sunan大叔'})
merge (m:Movie{title:'苏南大叔在北京'})
merge (r:Review{rating:9,mergedAt:'2022-11-11 11:11',content:'好看'})
merge (u)-[:AUTHORED]->(r)
merge (m)-[:HAS_REVIEW]->(r)
merge (u1:User{username:'sunan'})
merge (m1:Movie{title:'传奇人物:苏南大叔'})
merge (r1:Review{rating:8,mergedAt:'2022-11-11 11:12',content:'非常好看'})
merge (u1)-[:AUTHORED]->(r1)
merge (m1)-[:HAS_REVIEW]->(r1)
merge (u2:User{username:'苏南大叔'})
merge (m2:Movie{title:'苏南大叔拯救世界'})
merge (r2:Review{rating:8,mergedAt:'2022-11-11 11:18',content:'特别好看'})
merge (u2)-[:AUTHORED]->(r2)
merge (m2)-[:HAS_REVIEW]->(r2)
这里使用merge
而没有使用create
的理由,如下所示:
执行query
这里就随便执行几个graphql
查询试试,具体的说明信息请参考后续文章。
查询所有的电影及平均评分:
query ExampleQuery {
movies {
title
averageRating
}
}
查询所有的用户:
query ExampleQuery {
users {
username
}
}
添加一个新的电影:
mutation CreateMovies($input: [MovieCreateInput!]!) {
createMovies(input: $input) {
info {
bookmark
}
}
}
提交的数据:
{
"input": [
{
"title": "苏南大叔闯情关"
}
]
}
相关链接
给出neo4j
的基本使用资料链接,如下:
结束语
更多经验文章,请点击苏南大叔的博客文章:
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。