GraphQL ist datenbankunabhängig, sodass Sie alles verwenden können, was Sie normalerweise verwenden, um mit der Datenbank zu interagieren, und die resolve
der Abfrage oder Mutation verwenden Methode zum Aufrufen einer von Ihnen definierten Funktion, die der Datenbank etwas abruft/hinzufügt.
Ohne Relais
Hier ist ein Beispiel für eine Mutation unter Verwendung des Promise-basierten Knex-SQL-Abfragegenerators, zunächst ohne Relay, um ein Gefühl für das Konzept zu bekommen. Ich gehe davon aus, dass Sie in Ihrem GraphQL-Schema einen userType mit drei Feldern erstellt haben:id
, username
, und created
:alle erforderlich, und dass Sie einen getUser
haben bereits definierte Funktion, die die Datenbank abfragt und ein Benutzerobjekt zurückgibt. In der Datenbank habe ich auch ein password
Spalte, aber da ich das nicht abgefragt haben möchte, lasse ich es aus meinem userType
weg .
// 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,
})
),
},
}),
});
Da Postgres die id
erstellt für mich und ich berechne den created
timestamp, ich brauche sie nicht in meiner Mutationsabfrage.
Der Relaisweg
Verwenden der Helfer in graphql-relay
und es hat mir geholfen, mich ziemlich eng an das Staffel-Starter-Kit zu halten, weil es eine Menge auf einmal zu verarbeiten war. Relay erfordert, dass Sie Ihr Schema auf eine bestimmte Weise einrichten, damit es ordnungsgemäß funktioniert, aber die Idee ist die gleiche:Verwenden Sie Ihre Funktionen, um in den Auflösungsmethoden Daten aus der Datenbank abzurufen oder zu ihr hinzuzufügen.
Ein wichtiger Vorbehalt ist, dass der Relay-Weg erwartet, dass das Objekt von getUser
zurückgegeben wird ist eine Instanz einer Klasse User
, also müssen Sie getUser
ändern um dem Rechnung zu tragen.
Das letzte Beispiel mit Relay (fromGlobalId
, globalIdField
, mutationWithClientMutationId
und nodeDefinitions
sind alle von 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),
},
}),
});