如何在Azure Functions的Apollo Server中连接Cosmos DB与Blob存储?
多数据库连接解决方案(Apollo Server + Azure Functions)
针对你的场景,不需要拆分多个Apollo Server,以下是几种适配Azure Functions的可行方案:
方案1:扩展现有DataSource,集成双数据源
这是最符合Apollo设计模式的方案,通过dataSources同时注入Cosmos DB和Blob Storage的数据源,无需拆分端点。
步骤1:创建Blob Storage数据源类
新建../data/blobDataSource.js:
import { DataSource } from 'apollo-datasource'; import { BlobServiceClient } from '@azure/storage-blob'; export class BlobDataSource extends DataSource { constructor() { super(); // 从Azure Functions配置的环境变量读取连接字符串 this.blobServiceClient = BlobServiceClient.fromConnectionString(process.env.AZURE_STORAGE_CONNECTION_STRING); } // 示例:获取所有存储容器 async listContainers() { const containers = []; for await (const container of this.blobServiceClient.listContainers()) { containers.push({ name: container.name, createdAt: container.createdOn }); } return containers; } // 添加自定义Blob操作方法,比如上传文件 async uploadBlob(containerName, blobName, content) { const containerClient = this.blobServiceClient.getContainerClient(containerName); const blockBlobClient = containerClient.getBlockBlobClient(blobName); await blockBlobClient.upload(content, content.length); return { success: true, blobUrl: blockBlobClient.url }; } }
步骤2:组合双数据源
修改../data/index.js,导出包含双数据源的工厂函数:
import { cosmosDataSources } from './cosmosDataSource'; // 你的原有Cosmos数据源 import { BlobDataSource } from './blobDataSource'; export const dataSources = () => ({ cosmos: cosmosDataSources(), // 保持原有Cosmos数据源的初始化逻辑 blob: new BlobDataSource() });
步骤3:更新Apollo Server配置
修改主文件,替换原有的dataSources配置:
import { GraphQLFileLoader } from "@graphql-tools/graphql-file-loader"; import { loadSchemaSync } from "@graphql-tools/load"; import { addResolversToSchema } from "@graphql-tools/schema"; import { ApolloServer } from "apollo-server-azure-functions"; import { join } from "path"; import { dataSources } from "../data/index"; // 导入组合后的数据源 import resolvers from "../resolvers"; const schema = loadSchemaSync( join(__dirname, "..", "..", "graphql", "schema.graphql"), { loaders: [new GraphQLFileLoader()], } ); const server = new ApolloServer({ schema: addResolversToSchema({ schema, resolvers }), dataSources, // 使用组合后的数据源工厂函数 context: {}, }); export default server.createHandler({ cors: { origin: ['*', "https://studio.apollographql.com"], methods: ["GET", "POST", "OPTIONS"], allowedHeaders: ["access-control-allow-credentials", "access-control-allow-origin", "content-type"] }, });
步骤4:在Resolver中调用双数据源
修改resolvers,通过dataSources访问两个数据源:
const resolvers = { Query: { // 调用Cosmos DB数据 getCosmosItems: async (_parent, _args, { dataSources }) => { return dataSources.cosmos.getItems(); }, // 调用Blob Storage数据 getBlobContainers: async (_parent, _args, { dataSources }) => { return dataSources.blob.listContainers(); } }, Mutation: { uploadToBlob: async (_parent, { containerName, blobName, content }, { dataSources }) => { return dataSources.blob.uploadBlob(containerName, blobName, content); } } }; export default resolvers;
方案2:创建多个Azure Functions端点(拆分Apollo Server)
如果两个数据源的业务完全独立,可以为每个数据库创建独立的Azure Function:
- 复制现有GraphQL Function文件夹,命名为
graphql-blob - 在新Function中初始化仅连接Blob Storage的Apollo Server,使用独立的Schema和Resolvers
- 修改新Function的
function.json,设置路由为/api/graphql-blob - 原有Function保持连接Cosmos DB,路由为
/api/graphql
此方案适合业务完全隔离的场景,但会增加维护成本。
方案3:直接在Resolver中初始化客户端(简单场景)
如果Blob操作逻辑简单,可跳过DataSource,直接在Resolver中初始化客户端:
import { BlobServiceClient } from '@azure/storage-blob'; const resolvers = { Query: { getBlobContainers: async () => { const blobServiceClient = BlobServiceClient.fromConnectionString(process.env.AZURE_STORAGE_CONNECTION_STRING); const containers = []; for await (const container of blobServiceClient.listContainers()) { containers.push({ name: container.name }); } return containers; } } };
此方案适合快速实现,但不利于代码复用和测试。
内容的提问来源于stack exchange,提问作者welsea
相关产品推荐
相关产品推荐

