如何连接 GraphQL 和 PostgreSQL

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35940528/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 06:11:53  来源:igfitidea点击:

How to connect GraphQL and PostgreSQL

postgresqlgraphql

提问by Ska

GraphQL has mutations, Postgres has INSERT; GraphQL has queries, Postgres has SELECT's; etc., etc.. I haven't found an example showing how you could use both in a project, for example passing all the queries from front end (React, Relay) in GraphQL, but to a actually store the data in Postgres.

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

Does anyone know what Facebook is using as DB and how it's connected with GraphQL?

有谁知道 Facebook 使用什么作为 DB 以及它是如何与 GraphQL 连接的?

Is the only option of storing data in Postgres right now to build custom "adapters" that take the GraphQL query and convert it into SQL?

现在在 Postgres 中存储数据以构建自定义“适配器”以获取 GraphQL 查询并将其转换为 SQL 是唯一的选择吗?

采纳答案by Eric Streeper

GraphQL is database agnostic, so you can use whatever you normally use to interact with the database, and use the query or mutation's resolvemethod to call a function you've defined that will get/add something to the database.

GraphQL 与数据库无关,因此您可以使用通常用于与数据库交互的任何内容,并使用查询或突变的resolve方法来调用您定义的函数,该函数将获取/添加某些内容到数据库中。

Without Relay

无中继

Here is an example of a mutation using the promise-based Knex SQL query builder, first without Relay to get a feel for the concept. I'm going to assume that you have created a userType in your GraphQL schema that has three fields: id, username, and created: all required, and that you have a getUserfunction already defined which queries the database and returns a user object. In the database I also have a passwordcolumn, but since I don't want that queried I leave it out of my userType.

下面是一个使用基于承诺的Knex SQL 查询构建器的突变示例,首先不使用 Relay 来感受一下这个概念。我会假设你已经在这三个领域的GraphQL架构创建一个用户类型:idusernamecreated:所有必需的,而你有一个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,
        })
      ),
    },
  }),
});

Since Postgres creates the idfor me and I calculate the createdtimestamp, I don't need them in my mutation query.

由于 Postgresid为我创建了并且我计算了created时间戳,因此我的变异查询中不需要它们。

The Relay Way

接力方式

Using the helpers in graphql-relayand sticking pretty close to the Relay Starter Kithelped me, because it was a lot to take in all at once. Relay requires you to set up your schema in a specific way so that it can work properly, but the idea is the same: use your functions to fetch from or add to the database in the resolve methods.

graphql-relayRelay Starter Kit 中使用帮助器并非常接近Relay Starter Kit对我有帮助,因为一次要吸收很多东西。Relay 要求您以特定方式设置您的模式,以便它可以正常工作,但想法是相同的:使用您的函数在解析方法中从数据库中获取或添加到数据库中。

One important caveat is that the Relay way expects that the object returned from getUseris an instance of a class User, so you'll have to modify getUserto accommodate that.

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

The final example using Relay (fromGlobalId, globalIdField, mutationWithClientMutationId, and nodeDefinitionsare all from graphql-relay):

使用 Relay ( fromGlobalId, globalIdField, mutationWithClientMutationId, and nodeDefinitionsare all from 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),
    },
  }),
});

回答by Andy Carlson

We address this problem in Join Monster, a library we recently open-sourced to automatically translate GraphQL queries to SQL based on your schema definitions.

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

回答by Konstantin Tarkus

This GraphQL Starter Kitcan be used for experimenting with GraphQL.js and PostgreSQL:

这个GraphQL Starter Kit可用于试验 GraphQL.js 和 PostgreSQL:

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

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

(disclaimer: I'm the author)

(免责声明:我是作者)

回答by Alex

Have a look at graphql-sequelizefor how to work with Postgres.

查看graphql-sequelize了解如何使用 Postgres。

For mutations (create/update/delete) you can look at the examples in the relay repofor instance.

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

回答by Todd

Postgraphile https://www.graphile.org/postgraphile/is Open Source

Postgraphile https://www.graphile.org/postgraphile/是开源的

Rapidly build highly customisable, lightning-fast GraphQL APIs

PostGraphile is an open-source tool to help you rapidly design and serve a high-performance, secure, client-facing GraphQL API backed primarily by your PostgreSQL database. Delight your customers with incredible performance whilst maintaining full control over your data and your database. Use our powerful plugin system to customise every facet of your GraphQL API to your liking.

快速构建高度可定制、闪电般快速的 GraphQL API

PostGraphile 是一个开源工具,可帮助您快速设计和提供主要由 PostgreSQL 数据库支持的高性能、安全、面向客户端的 GraphQL API。以令人难以置信的性能取悦您的客户,同时保持对您的数据和数据库的完全控制。使用我们强大的插件系统根据自己的喜好自定义 GraphQL API 的各个方面。

回答by Joe Ng'ethe

Have a look at SequelizeJSwhich is a promise based ORM that can work with a number of dialects; PostgreSQL, MySQL, SQLite and MSSQL

看看SequelizeJS,它是一个基于Promise的 ORM,可以使用多种方言;PostgreSQL、MySQL、SQLite 和 MSSQL

The below code is pulled right from its example

下面的代码是从它的例子中拉出来的

const Sequelize = require('sequelize');
const sequelize = new Sequelize('database', 'username', 'password', {
  host: 'localhost',
  dialect: 'mysql'|'sqlite'|'postgres'|'mssql',

  pool: {
    max: 5,
    min: 0,
    acquire: 30000,
    idle: 10000
  },

  // SQLite only
  storage: 'path/to/database.sqlite',

  // http://docs.sequelizejs.com/manual/tutorial/querying.html#operators
  operatorsAliases: false
});

const User = sequelize.define('user', {
  username: Sequelize.STRING,
  birthday: Sequelize.DATE
});

sequelize.sync()
  .then(() => User.create({
    username: 'janedoe',
    birthday: new Date(1980, 6, 20)
  }))
  .then(jane => {
    console.log(jane.toJSON());
  });

回答by pepestar

Probably FB using mongodb or nosql in backend. I've recently read a blog entry which explain how to connect to mongodb. Basically, you need to build a graph model to match the data you already have in your DB. Then write resolve, reject function to tell GQL how to behave when posting a query request.

可能是在后端使用 mongodb 或 nosql 的 FB。我最近阅读了一篇博客文章,其中解释了如何连接到 mongodb。基本上,您需要构建一个图形模型来匹配您数据库中已有的数据。然后编写 resolve、reject 函数来告诉 GQL 在发布查询请求时如何表现。

See https://www.compose.io/articles/using-graphql-with-mongodb/

https://www.compose.io/articles/using-graphql-with-mongodb/