Skip to content

Graphql相关的框架和The Graph的多链查询

上文:The Graph GraphNode 和 Subgraph 本地搭建

前面已经部署好了graph-node和使用the graph client进行事件部署

Javascript Graphql相关的框架

相同点

  • GraphQL 支持:所有三个框架都支持 GraphQL 查询和变更操作。
  • 扩展性:都可以通过插件或自定义逻辑进行扩展。
  • 多环境支持:都可以在多种环境中运行,如服务器、无服务器架构等。

不同点

  • 数据源支持:GraphQL Mesh 支持多种非 GraphQL 数据源,而 Apollo Server 和 GraphQL Yoga 主要专注于 GraphQL 数据源。
  • 设置和配置:GraphQL Yoga 提供开箱即用的默认配置,适合快速启动;Apollo Server 则更适合需要细粒度控制和生产环境的应用。
  • 性能优化:GraphQL Yoga 强调性能优化,如缓存和持久化查询;Apollo Server 提供生产就绪的特性,适合大规模应用。

关于代码方面的不同点

  • GraphQL Mesh:基本不用写代码,可以自动从多种数据源生成 schema。
  • GraphQL Yoga:需要手动提供 schema,可以使用 codegen 根据schema生成代码,支持多种构建库,如 Pothos、GraphQL Nexus、gqtx 等,提供了灵活性和多样性。
  • Apollo Server:需要手动编写 schema,可以使用 codegen 根据schema生成代码,但是实际的查询逻辑实现需要手写,适合需要精细控制和自定义的应用。它提供了强大的插件系统和广泛的社区支持,适合复杂的生产环境。

GraphQL Mesh 可以直接根据多种数据源(如 REST、gRPC、OpenAPI 等)自动生成 GraphQL schema。这使得它非常适合需要整合多个异构数据源的场景。

TIP

因为 the graph 的项目在我们部署好多个链对应的 graph node 之后,已经有了多个可以查询的节点, the graph 官方提供了 graph client 生成工具

首先,请确保在您的项目中安装 [The Graph Client CLI]:

shell
yarn add -D @graphprotocol/client-cli
# or, with NPM:
npm install --save-dev @graphprotocol/client-cli

创建一个配置文件(名为.graphclientrc.yml )并指向 The Graph 提供的 GraphQL 端点,例如:

点我查看 .graphclientrc.yml 代码
yaml
# .graphclientrc.yml
sources:
  - name: uniswapv2
    handler:
      graphql:
        endpoint: https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2
        
  # 需要安装额外的依赖,具体参考 https://the-guild.dev/graphql/mesh/docs/handlers/handlers-introduction  
  - name: postgres_db
    handler:
      postgraphile:
        connectionString: postgres://dbuser:dbpwd@ip:54321/dbname

通过命令 graphclient build 直接从 endpoint 和 数据库🔗 读取元数据生成代码到项目根目录

使用 graphclient serve-dev 可以直接启动一个 graph-mesh 服务用于查询

项目集成

graph-mesh 官方还未提供将 graph-mesh 集成到 nestjs 使用的方法

1. 在 mesh.controller.ts 控制器中集成 createBuiltMeshHTTPHandler。

typescript
// mesh.controller.ts
import { Controller, All, Req, Res, Next } from '@nestjs/common';
import { createBuiltMeshHTTPHandler } from '../../.graphclient';

@Controller('graphql')
export class GraphqlController {
  private meshHTTP: ReturnType<typeof createBuiltMeshHTTPHandler>; 

  constructor() {
    this.meshHTTP = createBuiltMeshHTTPHandler(); 
  }

  @All('/')
  async handleGraphQL(@Req() req: Request, @Res() res: Response) {
    return this.meshHTTP(req, res); 
  }
}

2. 新建 mesh.module.ts, 将控制器添加到模块中。

typescript
// mesh.module.ts
import { Module } from '@nestjs/common';
import { GraphqlController } from "./mesh.controller";

@Module({
    controllers: [GraphqlController], 
})
export class GraphqlModule {}

3. 在 AppModule 中导入 GraphqlModule

typescript
// app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { GraphqlModule } from "./graph-mesh-support/mesh.module";

@Module({
    imports: [GraphqlModule], 
    controllers: [AppController],
    providers: [AppService],
})
export class AppModule {}

现在通过 http://localhost:3000/graphql 应该可以访问到 graph-mesh 的服务

eg:

graphql
query MyQuery {
  events(
    first: 10
    where: {or: [{to: "0x340a6fc05592aa06feff089d391269ad0a818c39"}, {from: "0x340a6fc05592aa06feff089d391269ad0a818c39"}]}
  ) {
    id
    price
    from
    to
  }
}
附:Apollo Server 实现 graphQL 查询修改
typescript
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';

const typeDefs = `#graphql
  type Book {
    title: String
    author: String
  }

  type Query {
    books: [Book]
    transfers(where:String, first:Int): [Transfer]
  }
  
  type Mutation {
    updateBook(title: String!, author: String!): Book
    addBook(title: String!, author: String!): Book
  }
`;

const books = [
    {
        title: 'The Awakening',
        author: 'Kate Chopin',
    },
    {
        title: 'City of Glass',
        author: 'Paul Auster',
    },
];


const resolvers = {
    Query: {
        books: () => books,
    },
    Mutation: {
        updateBook: (_, { title, author }) => {
            const book = books.find(book => book.title === title);
            if (book) {
                book.author = author;
            }
            return book;
        },
        addBook: (_, { title, author }) => {
            const newBook = { title, author };
            books.push(newBook);
            return newBook;
        }
    }
};

const server = new ApolloServer({
    typeDefs,
    resolvers,
});
 
const { url } = await startStandaloneServer(server, {
    listen: { port: 4000 },
});

console.log(`🚀  Server ready at: ${url}`);

文章来源于自己总结和网络转载,内容如有任何问题,请大佬斧正!联系我