【问题标题】:How to change DB connections on the fly with GraphQL?如何使用 GraphQL 即时更改数据库连接?
【发布时间】:2019-10-08 20:24:10
【问题描述】:

我们有一个 GraphQL 服务器设置,它在不同的客户端系统上使用完全相同的一组 GraphQL 调用。这些客户端具有不变的完全相同的表/结构。

我想进行 GraphQL 调用,以指示要使用的数据库连接。或者,如果 GraphQL 有类似的替代方案,我会全力以赴。

我一直在谷歌搜索、论坛潜水和文档扫描......

【问题讨论】:

    标签: database graphql database-connection apollo-server


    【解决方案1】:

    一种可能的解决方案是创建一个directives

    const typeDefs = gql`
    
      directive @db(client: DbClient) on FIELD_DEFINITION
    
      type DbClient {
         DB_CLIENT_1
         DB_CLIENT_2
      } 
    
      type Query {
        users: [User] @db
      }
    `;
    
    
    // Directive
    
    
    // db client connection config 
    const dbConnectionConfig = {
       DEFAULT : {...},
       DB_CLIENT_1: {...},
       DB_CLIENT_2: {...}
    }
    
    class DbClientDirective extends SchemaDirectiveVisitor {
      public visitFieldDefinition(field) {
        const { resolve = defaultFieldResolver } = field;
        const { client } = this.args;
    
        field.args.push({
          name: 'client',
          type: GraphQLString
        });
    
        field.resolve = async function (
          source,
          { client, ...otherArgs },
          context,
          info,
        ) {
    
    
          let connectionConfig = dbConnectionConfig.DEFAULT;
          if(Object.prototype.hasOwnProperty.call(dbConnectionConfig, client)) {
            connectionConfig = dbConnectionConfig[client];
          }
    
          /**
           create a DB client with the given config. Even you can persist the DB connection is a hashMap such that you don't need to establish a new connection every time.
          **/
    
          const dbSession = new DbClient(connectionConfig);
    
          // put the dbSession in a context such that it can be used by the resolver.
    
          context.dbSession = dbSession;
          return resolve.call(this, source, otherArgs, context, info);
        };
    
        field.type = GraphQLString;
      }
    }
    
    // UserResolver.js
    
    const UserResolver = {
      Query: {
        users(async (parent, args, context, info) => {
          const dbSession = context.dbSession;
          // use the dbSession to fetch the results. Note, here resolve need not to know about the db client details.
    
          return dbSession.findAll();
        }
    }
    
    
    
    const resolvers = merge(
      UserResolver
    );
    
    const server = new ApolloServer({
      typeDefs,
      resolvers,
      schemaDirectives: {
        date: DbClientDirective
      }
    });
    
    server.listen().then(({ url }) => {
      console.log(`? Server ready at ${url}`);
    });
    
    

    您现在可以将客户端参数传递给用户查询以指示使用哪个数据库连接。

    示例 1 - 这将使用 DEFAULT 作为数据库客户端

    query {
       users {
          name
          userId 
       }
    }
    
    

    示例 2 - 这将使用 DB_CLIENT_1 作为数据库客户端

    query {
       users(client: DB_CLIENT_1) {
          name
          userId 
       }
    }
    
    

    【讨论】:

      猜你喜欢
      • 2021-09-11
      • 2017-07-27
      • 2020-01-12
      • 1970-01-01
      • 2011-11-28
      • 2019-08-13
      • 2021-09-11
      • 1970-01-01
      相关资源
      最近更新 更多