使用 GraphQL 和 Prisma 使 SQL 查询变得简单!

在本篇博客中,我们将看到如何使用Prisma和GraphQL构建SQL查询机制,我们将使用Apollo Client和GraphQL Server使用Express使用GraphQL。

这里使用的技术堆栈是:
GraphQL,Prisma PGSQL转储,Express(推断GraphQL后端服务器)。

如果您想要GraphQL查询,请与我们的后端接口进行通信,我们可能需要做我在React下在下面做的事情,这只是一个配置部分,我想从技术上讲,我们如何在前端部分配置GraphQL。

const client = new ApolloClient({
  uri: import.meta.env.VITE_APP_GRAPHQL_API,
  cache: new InMemoryCache(),
});

然后,我们将使用它像包装应用程序组件一样使用它,因为我们将在整个应用程序中使用客户端。

 <ApolloProvider client={client}>
  <App />
 </ApolloProvider>

上述代码必须在main.tsx文件中或index.ts文件中写入。以上代码在阿波罗的帮助下创建客户端-客户端库用来创建一个用于使用GraphQL的客户端的使用,它需要两个参数URI,不过是GraphQL API的后端推断和我们定义InmemoryCache的缓存参数() 如果在没有网络请求的情况下将查询存储在本地缓存存储中,则阿波罗客户端会立即响应。

现在,我们需要集中精力,以推断GraphQL Server在其中突变和获取我们的帖子数据-GRES数据转储

让我们从graphql的后端设置开始,然后是prisma

在这里,我们看不到要设置的配置的太多,但是只有为服务客户端请求服务的Apollo服务器,我们的主要重点是准确而精确地制作解决方案函数和架构文件,因为有时可能会很混乱。产品代码库变得非常庞大。

在我的 ./index.js

const server = new ApolloServer({
  schema,                        // you executable schema file
  context: ({ req }) => ({
    db,                         // your database connection
  }),
  plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
});

await server.start();

就我而言,我正在使用Postgres数据库,所以我将使用PG-承诺制作数据库实例并制作连接字符串。我还附加了我们如何从.env文件中使用它,就好像有些新手读取博客一样,他们可能会有意义地开发生产 /行业应用程序。

const pgp = pgPromise();
export const db = pgp({
  connectionString:  `postgres://${process.env.DB_USER}:${process.env.DB_PASSWORD}@${process.env.DB_HOST}:${process.env.DB_PORT}/${process.env.DB_DATABASE}` ,
});

现在让我们求助于可执行模式文件并赠送给阿波罗服务器

import makeExecutableSchema from  "graphql-tools"  // also add it into the file

const schema = makeExecutableSchema({ typeDefs, resolvers });

那么什么是Typedef和解析器?

Typedefs不过是一个架构文件,其中提到的字段的数据类型(类似于Typescript中的类型),我将添加一些我们在文件中提到的内容以及一些标量类型,我们如何管理一些标量类型以及如何管理我们是否使用GraphQLScalArtypes创建了一些自定义TypeDEF。还链接了文档 apolagraphql 用于使模式更好,声音。

也在我的 ./schema.js

让我们假设我正在做类似的事情 user_secrets 让我的DB以以下方式诱惑

 type sus_users_talez{
        id: Int!,
        created_at: TimestampWithTimezone!,
        updated_at: TimestampWithTimezone,
        deleted_at: TimestampWithTimezone,
        name: String,
        sus_created_at: TimestampWithTimezone,
        sus_updated_at: TimestampWithTimezone,
        visibility: String,
        workflows: [String],

    }

在这里,您可以看到我有Timestampwithtimezone,这是一个自定义Typedef,我们将在微型中创建它

但是在此之前,我想展示我们将如何使架构文件更加好,以上只是类型的示例

export const typeDefs = `#graphql
    scalar TimestampWithTimezone
    scalar JSON

 type sus_users_talez{
        id: Int!,
        created_at: TimestampWithTimezone!,
        updated_at: TimestampWithTimezone,
        deleted_at: TimestampWithTimezone,
        name: String,
        sus_created_at: TimestampWithTimezone,
        sus_updated_at: TimestampWithTimezone,
        visibility: String,
        workflows: [String],


    }


// this typedef will be responsible for Querying (Remember useQuery in ApolloGraphQL for fetching data from server)

// Note : I have also shown how it will take parameter for Pagination and a id for specifc user data. 

type Query {

 # Query to get all sus_users_talez
  getAllSusUsers(limit:Int, offset:Int): [sus_users_talez]

 # Query to get sus_users_talez by ID
  getSusUser(id: Int!): sus_users_talez

}

// Similarly we will create a Mutation typedef to accomplish Querying from frontend.

 type Mutation {
        # mutation endpoint for customSQL queries from frontend
        customSQLQuery(limit:Int, offset: Int, sql: String! , user_id: String!): JSON

}`

也让我回到自定义标量类型:) ,我们只需将其添加到我们在同一文件中导出的上述类型中,或从新文件中创建和导出它。

还要注意GraphQL单独支持JSON,上面在突变中,我们将其用作Frontend的用户将发送JSON格式的有效负载。

import { GraphQLScalarType } from  "graphql" ;


export const TimestampWithTimezone = new GraphQLScalarType({
  name:  "TimestampWithTimezone" ,
  description:  "Timestamp with timezone offset" ,
  serialize: (value) => {
    // Serialize a timestamp value from your database
    return value.toISOString();
  },
  parseValue: (value) => {
    // Parse a timestamp value from a client input
    return new Date(value);
  },
  parseLiteral: (ast) => {
    if (ast.kind === Kind.STRING) {
      // Parse a timestamp from an AST literal
      return new Date(ast.value);
    }
    return null;
  },
});

接下来是解析器功能,我们将如何创建一个解析器函数,该函数根据客户端的用户请求返回数据。

让我们开始从头开始构建我们的Resover文件:)

export const resolvers = {
  Query: {
    getAllSusUsersTalez: async (parent, { limit, offset }) => {
      try {
        // Use Prisma to fetch all sus_users_talez
        const allUsers = await prisma.sus_users_talez.findMany({
          skip: offset,
          take: limit,
        });
        return allUsers;
      } catch (error) {
        console.error( "Error fetching sus_users_talez:" , error);
        throw error;
      }
    },
}

 Mutation: {
    customSQLQuery: async (parent, { limit, offset, sql, user_id }) => {
      try {
        // handling the recent queries
        // fetching the user_details for the metaData
        const user = await prisma.talez.findUnique({
          where: {
            user_id: user_id,
          },
        });

        // keeping a track for complete data count without offset
        const countQuery =  `SELECT COUNT(*) FROM (${sql}) AS total` ;
        const totalCount = await prisma.$queryRawUnsafe(countQuery);


        const paginatedSQL =  `${sql} LIMIT ${limit} OFFSET ${offset}` ;
        const result = await prisma.$queryRawUnsafe(paginatedSQL);

        // Check if there are more items
        const hasMoreItems = offset + limit < totalCount[0]?.count;

        return { result: result, hasMoreItems };
      } catch (error) {
        console.error( "Error executing SQL query:" , error);
        return { message:  "Error Executing SQL Query, Try Different Query"  };
      }
    },
  }

在这里,我创建了一个查询功能,我尝试获取与SUS相关的所有数据_用户_Talez还添加了一个突变功能,如果用户需要按限制和偏移,他们也可以轻松地编写自定义SQL查询。

例如 Select * From sus_users_talez WHERE id="12345" 和Kaboom,您会得到结果。

PS:在Prisma之上构建将做出一些额外的努力,例如Prisma架构文件和迁移,如果您更改任何字段,如果您已经有像我这样的DB转储,则需要使用所有相关的架构的DB拉动,而您只需需要点击一个称为的命令 prisma db pull 您可以找到它的文档 Prisma

因此,现在您可以更充分地使用GraphQL从此处创建更多参考-SQL使用Express和任何前端框架。

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

琴歌声声送我

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值