GraphQL je databázový agnostik, takže k interakci s databází můžete použít cokoliv, co běžně používáte, a použít resolve
dotazu nebo mutace metoda pro volání funkce, kterou jste definovali a která něco získá/přidá do databáze.
Bez relé
Zde je příklad mutace pomocí nástroje pro vytváření dotazů Knex SQL založeného na slibech, nejprve bez Relay, abyste získali představu o konceptu. Budu předpokládat, že jste ve schématu GraphQL vytvořili userType, které má tři pole:id
, username
a created
:vše povinné a že máte getUser
již definovaná funkce, která se dotazuje na databázi a vrací objekt uživatele. V databázi mám také password
sloupec, ale protože nechci, aby byl dotazován, vynechám jej ve svém 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,
})
),
},
}),
});
Protože Postgres vytváří id
pro mě a já počítám created
timestamp, nepotřebuji je ve svém dotazu na mutaci.
Způsob relé
Použití pomocníků v graphql-relay
a pomohlo mi to, že jsem se držel docela blízko Relay Starter Kit, protože toho bylo hodně najednou. Relay vyžaduje, abyste nastavili své schéma specifickým způsobem, aby mohlo správně fungovat, ale myšlenka je stejná:použijte své funkce k načítání nebo přidávání do databáze v metodách řešení.
Jednou z důležitých výhrad je, že způsob přenosu očekává, že se objekt vrátí z getUser
je instancí třídy User
, takže budete muset upravit getUser
abychom tomu vyhověli.
Poslední příklad s použitím Relay (fromGlobalId
, globalIdField
, mutationWithClientMutationId
a nodeDefinitions
všechny jsou z 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),
},
}),
});