Comment connecter GraphQL et PostgreSQL

GraphQL a des mutations, Postgres A INSERT; GraphQL a des requêtes, Postgres a SELECT; etc., etc.. Je n'ai pas trouvé d'exemple montrant comment vous pourriez utiliser les deux dans un projet, par exemple en passant toutes les requêtes de front end (React, Relay) dans GraphQL, mais à un réellement stocker les données dans Postgres.

est-ce que Quelqu'un sait ce que Facebook utilise comme DB et comment il est connecté avec GraphQL?

est la seule option de stockage de données dans Postgres en ce moment pour construire personnalisé "adaptateurs" qui prennent la requête GraphQL et la convertissent en SQL?

28
demandé sur Ska 2016-03-11 15:40:20

6 réponses

GraphQL est agnostique de base de données, donc vous pouvez utiliser tout ce que vous utilisez normalement pour interagir avec la base de données, et utiliser la requête ou la mutation resolve méthode pour appeler une fonction que vous avez définie qui va obtenir/ajouter quelque chose à la base de données.

Sans Relais

voici un exemple de mutation utilisant leKNEX SQL query builder, d'abord sans relais pour se faire une idée du concept. Je vais supposer que vous avez créé un userType dans votre schéma GraphQL qui comporte trois champs: id,username et created: tous les requis, et que vous avez un getUser fonction déjà définie qui interroge la base de données et renvoie un objet utilisateur. Dans la base de données j'ai aussi un password colonne, mais comme je ne veux pas que cela soit demandé je le laisse en dehors de mon 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,
        })
      ),
    },
  }),
});

depuis Postgres crée le id pour moi et je calcule le created timestamp, Je n'en ai pas besoin dans ma requête de mutation.

Le Relais

utiliser les helpers dans graphql-relay et coller assez proche de l' Relais De Kit De Démarreur m'a aidé, parce que c'était beaucoup à encaisser d'un seul coup. Relay vous demande de configurer votre schéma d'une manière spécifique afin qu'il puisse fonctionner correctement, mais l'idée est la même: utilisez vos fonctions pour aller chercher ou ajouter à la base de données dans les méthodes resolve.

une mise en garde importante est que le relais s'attend à ce que l'objet revienne de getUser est une instance d'une classe User, donc vous devrez modifier getUser pour accommoder cela.

Le Dernier exemple utilisant Relay (fromGlobalId,globalIdField,mutationWithClientMutationId et nodeDefinitionsgraphql-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),
    },
  }),
});
22
répondu Eric Streeper 2016-03-11 23:04:59

nous abordons ce problème dans Rejoindre Monster, une bibliothèque que nous avons récemment ouvert-source pour traduire automatiquement les requêtes GraphQL en SQL basé sur vos définitions de schéma.

15
répondu Andy Carlson 2016-10-07 06:52:35

GraphQL Starter Kit peut être utilisé pour expérimenter avec GraphQL.js et PostgreSQL:

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

(disclaimer: je suis l'auteur)

6
répondu Konstantin Tarkus 2016-12-01 20:04:08

probablement FB utilisant mongodb ou nosql dans le backend. J'ai récemment lu un article de blog qui explique comment se connecter à mongodb. Fondamentalement, vous devez construire un modèle de graphique pour correspondre aux données que vous avez déjà dans votre DB. Puis écrire résoudre, rejeter la fonction pour dire à GQL comment se comporter lors de la publication d'une requête de requête.

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

-2
répondu pepestar 2016-05-22 05:45:48

regardez SequelizeJS qui est un ORM basé sur la promesse qui peut fonctionner avec un certain nombre de dialectes; PostgreSQL, MySQL, SQLite et MSSQL

le code ci-dessous est tiré à droite de son exemple

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());
  });
-3
répondu Joe Ng'ethe 2017-11-08 09:24:56