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?
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 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),
},
}),
});
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.
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)
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/
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());
});