sql >> Databasteknik >  >> RDS >> PostgreSQL

Hur man ansluter GraphQL och PostgreSQL

GraphQL är databasagnostisk, så du kan använda vad du normalt använder för att interagera med databasen och använda frågans eller mutationens resolve metod för att anropa en funktion du har definierat som ska hämta/lägga till något i databasen.

Utan relä

Här är ett exempel på en mutation som använder den löftesbaserade Knex SQL-frågebyggaren, först utan Relay för att få en känsla för konceptet. Jag kommer att anta att du har skapat en userType i ditt GraphQL-schema som har tre fält:id , username och created :allt krävs och att du har en getUser redan definierad funktion som frågar databasen och returnerar ett användarobjekt. I databasen har jag även ett password kolumn, men eftersom jag inte vill att det ska frågas utelämnar jag det från min 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,
        })
      ),
    },
  }),
});

Eftersom Postgres skapar id för mig och jag beräknar den created tidsstämpel, jag behöver dem inte i min mutationsfråga.

The Relay Way

Använder hjälparna i graphql-relay och att hålla mig ganska nära Relay Starter Kit hjälpte mig, för det var mycket att ta in på en gång. Relay kräver att du ställer in ditt schema på ett specifikt sätt så att det kan fungera korrekt, men tanken är densamma:använd dina funktioner för att hämta från eller lägga till i databasen i lösningsmetoderna.

En viktig varning är att reläsättet förväntar sig att objektet returneras från getUser är en instans av en klass User , så du måste ändra getUser för att tillgodose det.

Det sista exemplet med Relay (fromGlobalId , globalIdField , mutationWithClientMutationId och nodeDefinitions är alla från 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),
    },
  }),
});


  1. proxysql-admin Alternativ - ClusterControl ProxySQL GUI

  2. Oracle 12:Gå med på kommaseparerad lista?

  3. Utveckling av feltolerans i PostgreSQL

  4. Sätt att spåra raderad databas i SQL Server