TypeGraphQL与MongoDB:使用Mongoose构建NoSQL GraphQL服务

TypeGraphQL与MongoDB:使用Mongoose构建NoSQL GraphQL服务

【免费下载链接】type-graphql 【免费下载链接】type-graphql 项目地址: https://gitcode.com/gh_mirrors/typ/type-graphql

TypeGraphQL与MongoDB的组合为构建灵活的NoSQL GraphQL服务提供了强大支持。本教程将通过examples/typegoose/示例项目,展示如何使用Mongoose(通过Typegoose)实现数据建模、关系处理和GraphQL API开发。

技术架构概览

TypeGraphQL负责类型定义和 resolver 实现,MongoDB提供文档存储,Typegoose作为桥梁连接两者。核心组件包括:

  • 实体建模:使用TypeGraphQL装饰器定义GraphQL类型,同时通过Typegoose装饰器映射MongoDB集合
  • 中间件转换:处理Mongoose文档到TypeGraphQL对象的转换
  • 自定义标量:实现MongoDB ObjectId与GraphQL类型的映射

技术架构

环境配置与依赖

项目基础配置位于examples/typegoose/index.ts,关键依赖包括:

import { buildSchema } from "type-graphql";
import { connect } from "mongoose";
import { TypegooseMiddleware } from "./typegoose.middleware";
import { ObjectIdScalar } from "./object-id.scalar";

启动流程包含MongoDB连接、数据库初始化和GraphQL服务器启动:

// 创建数据库连接
const mongoose = await connect(process.env.DATABASE_URL!);
// 构建GraphQL schema
const schema = await buildSchema({
  resolvers: [RecipeResolver, RatingResolver],
  globalMiddlewares: [TypegooseMiddleware],
  scalarsMap: [{ type: Types.ObjectId, scalar: ObjectIdScalar }],
});

数据模型设计

实体定义

实体类同时标注GraphQL类型和MongoDB集合结构,以examples/typegoose/entities/recipe.ts为例:

@ObjectType()
export class Recipe {
  @Field()
  readonly id!: Types.ObjectId;

  @Field()
  @Property({ required: true })
  title!: string;

  @Field(_type => User)
  @Property({ ref: User, required: true })
  author!: Ref<User>;
}

export const RecipeModel = getModelForClass(Recipe);

自定义ObjectId标量

MongoDB的ObjectId类型需要自定义GraphQL标量处理,实现位于examples/typegoose/object-id.scalar.ts

export const ObjectIdScalar = new GraphQLScalarType({
  name: "ObjectId",
  description: "Mongo object id scalar type",
  serialize(value: unknown): string {
    if (!(value instanceof Types.ObjectId)) {
      throw new Error("ObjectIdScalar can only serialize ObjectId values");
    }
    return value.toHexString();
  },
  // 省略parseValue和parseLiteral实现
});

文档转换中间件

Mongoose文档需要转换为普通对象才能被GraphQL正确序列化,中间件实现见examples/typegoose/typegoose.middleware.ts

export const TypegooseMiddleware: MiddlewareFn = async (_, next) => {
  const result = await next();

  if (Array.isArray(result)) {
    return result.map(item => (item instanceof Model ? convertDocument(item) : item));
  }

  if (result instanceof Model) {
    return convertDocument(result);
  }

  return result;
};

数据流转

Resolver实现

Resolver处理GraphQL查询和变更,以examples/typegoose/resolvers/recipe.resolver.ts为例:

查询操作

@Query(_returns => Recipe, { nullable: true })
recipe(@Arg("recipeId", () => ObjectIdScalar) recipeId: Types.ObjectId) {
  return RecipeModel.findById(recipeId);
}

@Query(_returns => [Recipe])
async recipes(): Promise<Recipe[]> {
  return RecipeModel.find({});
}

变更操作

@Mutation(_returns => Recipe)
async addRecipe(
  @Arg("recipe") recipeInput: RecipeInput,
  @Ctx() { user }: Context,
): Promise<Recipe> {
  const recipe = new RecipeModel({
    ...recipeInput,
    author: user.id,
  });

  await recipe.save();
  return recipe;
}

字段解析器

处理关联数据加载:

@FieldResolver()
async author(@Root() recipe: Recipe): Promise<User> {
  return (await UserModel.findById(recipe.author))!;
}

实际查询示例

examples/typegoose/examples.graphql提供了完整的查询示例:

query GetRecipe {
  recipe(recipeId: "64551384aac388414b391778") {
    _id
    title
    ratings {
      value
      user {
        nickname
      }
    }
    author {
      nickname
      email
    }
  }
}

查询结果

项目结构与扩展

完整项目结构可参考examples/typegoose/目录,主要包括:

  • entities/: 数据模型定义
  • resolvers/: GraphQL解析器
  • types/: 输入输出类型定义
  • helpers.ts: 数据库初始化工具

官方文档:docs/ 项目教程:README.md

通过这种架构,开发者可以快速构建类型安全、关系清晰的GraphQL服务,同时充分利用MongoDB的文档模型优势。

【免费下载链接】type-graphql 【免费下载链接】type-graphql 项目地址: https://gitcode.com/gh_mirrors/typ/type-graphql

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

抵扣说明:

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

余额充值