我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

在实际的graphql应用中,apollo server在某种意义上成了graphql的代名词。在neo4j+graphql的官方例子中,第一个例子migration就是基于apollo server的代码实现。在本文中,苏南大叔将对这个例子做初步的解读。

苏南大叔:neo4j结合graphql,解读第一个例子migration - neo4j-graphql-migration
neo4j结合graphql,解读第一个例子migration(图10-1)

大家好,这里是苏南大叔的程序如此灵动博客,这里记录苏南大叔和计算机代码的故事。本文描述如何基于apollo serverneo4j,实现graphql接口。测试环境:@neo4j/graphql@3.12.0neo4j-driver@5.1.0apollo-server@3.10.3neo4j@4.4.10node@16.14.2

测试代码

本文的测试代码来自于下面的网址:

苏南大叔:neo4j结合graphql,解读第一个例子migration - example-migration
neo4j结合graphql,解读第一个例子migration(图10-2)

下载回来后,使用yarn install安装相关依赖,然后执行npm start或者yarn start,打开apollo server的接口检测界面,如下图所示:

苏南大叔:neo4j结合graphql,解读第一个例子migration - apollo-server
neo4j结合graphql,解读第一个例子migration(图10-3)

apollo server的使用过程,可以参考下面这篇文章:

代码解读之主体框架

这个examplemigration代码非常简单,主要分为以下几个部分(为了叙述方便,对代码略有修改):

主体代码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"));

苏南大叔:neo4j结合graphql,解读第一个例子migration - neo4j-config
neo4j结合graphql,解读第一个例子migration(图10-4)

代码解读之结构定义

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包括两个部分,分别是:typeDefsresolvers。在本文中,typeDefs是自定义的,而resolvers是自动生成的。

这个typeDefs中,感叹号是表示"必选"。而@relationship则可以理解为outer join,就是外联查询。

苏南大叔:neo4j结合graphql,解读第一个例子migration - typedefs-gql
neo4j结合graphql,解读第一个例子migration(图10-5)

转换为neo4j代码

这里有两个既定的结论,可能和大家的习惯概念理解不同:

  • 实际上neo4j的配置信息错误的话,依然不影响这个graphql接口的生成,只不过执行接口的时候会报错而已。
  • neo4j数据库里面可以不用内置任何节点信息和数据,graphql接口正确执行neo4j语句接口,就可以创造一切数据。

苏南大叔:neo4j结合graphql,解读第一个例子migration - neo4j节点图
neo4j结合graphql,解读第一个例子migration(图10-6)

可能需要的清库代码【执行前,请清楚认知自己在干什么!】如下,参考文章:

match (n) detach delete n

为了表述逻辑的需要,根据上一个步骤中结构gql定义的内容,苏南大叔生成了一些neo4j语句,可以在neo4j browser中执行,以获得一些目标数据。gql定义中的directionout的关系是暂时不用考虑的,directionin的关系将体现在下面的构建语句中。

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
  }
}

苏南大叔:neo4j结合graphql,解读第一个例子migration - movies-query
neo4j结合graphql,解读第一个例子migration(图10-7)

查询所有的用户:

query ExampleQuery {
  users {
    username
  }
}

苏南大叔:neo4j结合graphql,解读第一个例子migration - 查询用户
neo4j结合graphql,解读第一个例子migration(图10-8)

添加一个新的电影:

mutation CreateMovies($input: [MovieCreateInput!]!) {
  createMovies(input: $input) {
    info {
      bookmark
    }
  }
}

提交的数据:

{
  "input": [
    {
      "title": "苏南大叔闯情关"
    }
  ]
}

苏南大叔:neo4j结合graphql,解读第一个例子migration - 添加新电影
neo4j结合graphql,解读第一个例子migration(图10-9)

苏南大叔:neo4j结合graphql,解读第一个例子migration - 添加成功
neo4j结合graphql,解读第一个例子migration(图10-10)

相关链接

给出neo4j的基本使用资料链接,如下:

结束语

更多经验文章,请点击苏南大叔的博客文章:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   node    知识图谱