如何连接GraphQL和PostgreSQL

Ska*_*Ska 42 postgresql graphql

GraphQL有突变,Postgres有INSERT; GraphQL有查询,Postgres有SELECT; 等等.我还没有找到一个示例,说明如何在项目中使用两者,例如在GraphQL中传递来自前端的所有查询(React,Relay),但实际存储在Postgres中的数据.

有谁知道Facebook正在使用什么作为数据库以及它如何与GraphQL连接?

现在是在Postgres中存储数据的唯一选择来构建自定义"适配器",它们接受GraphQL查询并将其转换为SQL吗?

Eri*_*per 29

GraphQL与数据库无关,因此您可以使用通常用于与数据库交互的任何内容,并使用查询或变异的resolve方法来调用您已定义的将向数据库添加/添加内容的函数.

没有接力

下面是一个使用基于promise的Knex SQL查询构建器的变异示例,首先没有Relay来了解该概念.我会假设你已经在这三个领域的GraphQL架构创建一个用户类型:id,usernamecreated:所有必需的,而你有一个getUser已定义的函数,查询数据库,并返回一个用户对象.在数据库中我也有一个password专栏,但由于我不想要查询,所以我将其留在了我的专栏中userType.

// db.js
// take a user object and use knex to add it to the database, then return the newly
// created user from the db.
const addUser = (user) => (
  knex('users')
  .returning('id') // returns [id]
  .insert({
    username: user.username,
    password: yourPasswordHashFunction(user.password),
    created: Math.floor(Date.now() / 1000), // Unix time in seconds
  })
  .then((id) => (getUser(id[0])))
  .catch((error) => (
    console.log(error)
  ))
);

// schema.js
// the resolve function receives the query inputs as args, then you can call
// your addUser function using them
const mutationType = new GraphQLObjectType({
  name: 'Mutation',
  description: 'Functions to add things to the database.',
  fields: () => ({
    addUser: {
      type: userType,
      args: {
        username: {
          type: new GraphQLNonNull(GraphQLString),
        },
        password: {
          type: new GraphQLNonNull(GraphQLString),
        },
      },
      resolve: (_, args) => (
        addUser({
          username: args.username,
          password: args.password,
        })
      ),
    },
  }),
});
Run Code Online (Sandbox Code Playgroud)

由于Postgres id为我创建并计算created时间戳,我在变异查询中不需要它们.

接力方式

使用辅助工具graphql-relay并且非常接近继电器入门工具包对我有帮助,因为它可以同时考虑到所有工作.中继要求您以特定方式设置模式,以使其可以正常工作,但想法是相同的:使用您的函数从解析方法中获取或添加到数据库.

一个重要的警告是,Relay方式期望返回的对象getUser是类的实例User,因此您必须进行修改getUser以适应该类.

使用继电器(最后一个例子中fromGlobalId,globalIdField,mutationWithClientMutationId,和nodeDefinitions都是从graphql-relay):

/**
 * We get the node interface and field from the Relay library.
 *
 * The first method defines the way we resolve an ID to its object.
 * The second defines the way we resolve an object to its GraphQL type.
 *
 * All your types will implement this nodeInterface
 */
const { nodeInterface, nodeField } = nodeDefinitions(
  (globalId) => {
    const { type, id } = fromGlobalId(globalId);
    if (type === 'User') {
      return getUser(id);
    }
    return null;
  },
  (obj) => {
    if (obj instanceof User) {
      return userType;
    }
    return null;
  }
);

// a globalId is just a base64 encoding of the database id and the type
const userType = new GraphQLObjectType({
  name: 'User',
  description: 'A user.',
  fields: () => ({
    id: globalIdField('User'),
    username: {
      type: new GraphQLNonNull(GraphQLString),
      description: 'The username the user has selected.',
    },
    created: {
      type: GraphQLInt,
      description: 'The Unix timestamp in seconds of when the user was created.',
    },
  }),
  interfaces: [nodeInterface],
});

// The "payload" is the data that will be returned from the mutation
const userMutation = mutationWithClientMutationId({
  name: 'AddUser',
  inputFields: {
    username: {
      type: GraphQLString,
    },
    password: {
      type: new GraphQLNonNull(GraphQLString),
    },
  },
  outputFields: {
    user: {
      type: userType,
      resolve: (payload) => getUser(payload.userId),
    },
  },
  mutateAndGetPayload: ({ username, password }) =>
    addUser(
      { username, password }
    ).then((user) => ({ userId: user.id })), // passed to resolve in outputFields
});

const mutationType = new GraphQLObjectType({
  name: 'Mutation',
  description: 'Functions to add things to the database.',
  fields: () => ({
    addUser: userMutation,
  }),
});

const queryType = new GraphQLObjectType({
  name: 'Query',
  fields: () => ({
    node: nodeField,
    user: {
      type: userType,
      args: {
        id: {
          description: 'ID number of the user.',
          type: new GraphQLNonNull(GraphQLID),
        },
      },
      resolve: (root, args) => getUser(args.id),
    },
  }),
});
Run Code Online (Sandbox Code Playgroud)


And*_*son 20

我们在Join Monster中解决了这个问题,这是我们最近开源的一个库,可以根据您的模式定义自动将GraphQL查询转换为SQL.


Kon*_*kus 8

这个GraphQL入门套件可用于试验GraphQL.js和PostgreSQL:

https://github.com/kriasoft/graphql-starter-kit - Node.js,GraphQL.js,PostgreSQL,Babel,Flow

(免责声明:我是作者)


Ale*_*lex 5

查看有关如何使用Postgres的graphql-sequelize

对于突变(创建/更新/删除),您可以查看中继回购中的示例。