graphql-server node版(三)

添加数据库

1、为什么选择prisma?

构建GraphQL服务器最大的难点是什么?

在实际应用程序中,您可能会遇到许多场景,其中实现解析器会变得非常复杂。特别是因为GraphQL查询可以嵌套多个级别,实现通常变得棘手并且很容易导致性能问题。大多数情况下,您还需要处理许多其他工作流程,例如身份验证,授权(权限),分页,过滤,实时,与第三方服务或遗留系统集成。

通常,在实现解析器并连接到数据库时,您有两个选项 - 这两个选项都不是很吸引人:

  • 直接访问数据库(通过编写SQL或使用其他NoSQL数据库API)
  • 使用为数据库提供抽象ORM,并允许您直接从编程语言访问它。

这两种都不太适合GraphQL.第一种直接在代码中迁入sql语句无法使用自动验证功能,全部要人工写,很困难。第二种ORM在处理简单请求时可以,但是面对复杂的深层次的请求变得比较困难。

prisma提供了一个GraphQL query engine负责解析请求。当我们使用prisma的时候,我们的解析函数通常做的事情就是把请求发送给GraphQL query engine。我们不用再去写解析函数,自己调用sql语句或orm来操作数据库,我们只要通过解析函数将请求发送给GraphQL query engine就好了,engine会负责解析查询并向数据库请求结果。在使用解析器将请求发送给engine时,我们使用prisma bindings,可以轻松的将请求发送给engine,通常只需要一行代码。

客户端GraphQL请求=》graphql-yoga接受请求,根据schema调用对应的解析函数(resolver)=》resolver通过prisma bindings 将请求发送到对应的prisma GraphQL API,=>prisma解析收到的请求并转换为对应的sql语句,然后向数据库发送请求=》数据库返回请求结果。

这样我们要在服务端做的工作仅仅是使用resolver解析函数将请求解析到对应到prisma GraphQL schema上。

因此有两层GraphQL,一层是应用层(app层),App层的shcema和resolver使用来处理客户端的GraphQL请求的,App层的schema和resolver仅仅是将请求带到了对应的(数据库层)prisma层的GraphQL API,prisma负责自动将请求转换为数据库能够读懂的语言,然后返回结果。

服务器端工作流程:

定义App层的schema

定义App才能schema对应的resolver

定义prisma层的schema。这里我们仅仅需要定义data model也就是我们项目中所需要的对象类型,比如说建一个汽车销售应用,我们仅仅需要定义汽车类、经销商类、门店类等,我们自己不需要再定义Query和Mutaition等根类,prisma会根据我们定义的data model自动为我们生成shcema,包括Query(单个和列表),Mutation(增删改查)等等功能。这个自动生成的schema也就是prisma提供的数据库层的GraphQL API,我们应该在App层的resolver中调用prisma层的schema.

prisma会根据schema和App层调用的对应的api来调用自己内部的解析函数生成sql语句来访问数据库,数据库根据请求返回结果。

举例:

我们在database层使用SDL定义下面一个data model:

type User {
  id: ID! @unique
  name: String!
}

  基于上面的data model ,prisma会为我们生成下面的schema,也就是database层可访问的api

type Query {
  users(where: UserWhereInput, orderBy: UserOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [User]!
  user(where: UserWhereUniqueInput!): User
}

type Mutation {
  createUser(data: UserCreateInput!): User!
  updateUser(data: UserUpdateInput!, where: UserWhereUniqueInput!): User
  deleteUser(where: UserWhereUniqueInput!): User
}

type Subscription {
  user(where: UserSubscriptionWhereInput): UserSubscriptionPayload
}

  实际上,实际的模式要大得多 - 为简洁起见,我们只包含了三种根类型和简单的CRUD操作。但API还允许各种其他操作(例如批量更新和删除)。如果您很好奇,可以在这里查看整个架构。

为什么不直接使用Prisma GraphQL API?

Prisma实际上只是数据库的接口。如果直接从前端或移动应用程序使用Prisma API,这与直接访问数据库类似。这可能会带来很大的安全问题。

 直接让用户访问数据库肯定不是一件很好的事情。在访问数据库前我们还有很多事情要做如:验证数据的有效性和合法性,判断客户的身份及权限等等一些操作。

此外,GraphQL的工作方式是,每个有权访问GraphQL API端点的人都可以从中检索整个 GraphQL模式 - 这称为内省如果您的客户直接与Prisma交谈,那么只需检查网络请求即可访问Prisma API的端点,每个人都可以看到您的整个数据库架构。

2、创建prisma数据库服务

(1)在hackernews-node文件夹下创建database目录,然后创建两个文件叫prisma.ymldatamodel.graphql

mkdir database
touch database/prisma.yml
touch database/datamodel.graphql 

prisma.yml是用来配置prisma 数据库服务的配置文件。datamodel.graphql是用来写database层的data model的,prisma将根据这个文件中的data model自动生成database层的schema,即database层的GraphQL api.

在datamoel.grahql文件中输入下面的data model:

type Link {
  id: ID! @unique
  createdAt: DateTime!
  description: String!
  url: String!
}

  datamodel定义与App层的schema.graphql中定义的Link主要差异有以下几点:

@unique:说明id在Link数据库表中是唯一字段,不会出现重复项。另外在prisma中,如果一个type中有id:ID!,那么prisma会根据id自动生成整个数据库全局唯一的ID.

新增createdAt:DateTime!字段,这个字段是由prisma自动管理的字段,并且在API中该字段是只读的。它自动存储Link创建的时间。此外,prisma还提供了另一个相似的字段updateAt:DateTime!存储link上次更新的时间。

在prisma.yam中增加下面的内容

# The HTTP endpoint for your Prisma API
endpoint: ''

# Points to the file that holds your data model
datamodel: datamodel.graphql

# You can only access the API when providing JWTs that are signed with this secret
secret: mysecret123

  endpoint:是Prsima API提供的端口地址。

  datamodel:指定我们定义data model的文件

  secret:指定访问Prisma API需要的根据该secret 生成的JWT,将JWT输入到Header中的Authorization,才能访问Prisma API。

在部署prisma服务之前,我们需要先安装一下prisma

npm install -g prisma

  现在我们可以部署prisma服务了

cd database
prisma deploy

  在部署过程中我们可以选择使用已有的数据库,使用docker创建一个或者使用prisma cloud提供的服务。

我们可以选择使用docker来创建一个数据库:

如postgre数据库:创建一个docker-compose.yml文件输入下列内容

version: '3'
services:
  prisma:
    image: prismagraphql/prisma:1.16
    restart: always
    ports:
    - "4466:4466"
    environment:
      PRISMA_CONFIG: |
        port: 4466
        databases:
          default:
            connector: postgres
            host: postgres
            port: 5432
            user: prisma
            password: prisma
            migrations: true
  postgres:
    image: postgres:10.5
    restart: always
    environment:
      POSTGRES_USER: prisma
      POSTGRES_PASSWORD: prisma
    volumes:
      - postgres:/var/lib/postgresql/data
volumes:
  postgres:

安装并启动prisma服务:

docker-compose up -d

  注意在windows下,启动服务后不能用localhost:4466访问,因为实际docker是在windows环境下虚拟了一个linux环境,因此要使用docker上显示的ip地址访问4466端口。

3、探索prisma服务,操作数据库。

如果使用直接访问网络上的prisma服务,打开网络服务器地址:4466无法显示playground,这是因为我们没有权限访问,可以在Header中输入jwt.

在database目录下,使用prisma token生成jwt token,然后将token输入到Header中。

{
  "Authorization": "Bearer __TOKEN__"
}

  等一会,我们便可以看到playground上的schema显示可用的api了。

现在我们可以直接使用数据库层的api来发送请求,如下:

增加一个link

mutation {
  createLink(data: {
    url: "www.prisma.io"
    description: "Prisma turns your database into a GraphQL API"
  }) {
    id
  }
}  

 

查询刚增加的link

query {
  links {
    id
    url
    description
  }
}

  可以发现,我们现在已经可以通过 prisma GrapQL API来操作数据库了。

 

posted @ 2018-09-09 18:41  tutu_python  阅读(315)  评论(0)    收藏  举报