You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用gql-compose-mongoose如何在关联mongoose schema中互存ObjectID并实现关联查询

实现步骤

你需要分别完成双向关联数据写入、关联查询解析器注册两部分逻辑,具体实现如下:

1. 双向关联写入实现

创建挑战时使用MongoDB事务保证用户和挑战文档的关联字段同时更新,避免数据不一致:

import mongoose from "mongoose";
import { schemaComposer } from 'graphql-compose';
import { User, UserTC } from './userSchema.js';
import { Challenge, ChallengeTC } from './challengeSchema.js';

// 自定义创建挑战的Mutation
schemaComposer.Mutation.addFields({
  createChallengeBindUser: {
    type: ChallengeTC.getType(),
    args: {
      userId: "MongoID!",
      task: "String!",
      description: "String!"
    },
    resolve: async (_, { userId, task, description }) => {
      const session = await mongoose.startSession();
      session.startTransaction();
      try {
        // 新建挑战,写入关联用户ID
        const [newChallenge] = await Challenge.create(
          [{ user: [userId], task, description }],
          { session }
        );
        // 更新用户文档,写入关联挑战ID
        await User.findByIdAndUpdate(
          userId,
          { $push: { challenge: newChallenge._id } },
          { session, new: true }
        );
        await session.commitTransaction();
        session.endSession();
        return newChallenge;
      } catch (err) {
        await session.abortTransaction();
        session.endSession();
        throw new Error(`操作失败: ${err.message}`);
      }
    }
  }
});

如果需要给已有挑战添加其他关联用户,可参照上述事务逻辑,新增对应Mutation即可。

2. 关联查询解析器注册

使用graphql-compose的addRelation方法注册关联字段,自动完成关联数据的populate查询:

// 给User类型添加查询关联挑战详情的字段
UserTC.addRelation('challengeList', {
  resolver: () => ChallengeTC.getResolver('findByIds'),
  prepareArgs: {
    _ids: (user) => user.challenge
  },
  projection: { challenge: true }
});

// 给Challenge类型添加查询关联用户详情的字段
ChallengeTC.addRelation('userList', {
  resolver: () => UserTC.getResolver('findByIds'),
  prepareArgs: {
    _ids: (challenge) => challenge.user
  },
  projection: { user: true }
});

3. 注册基础查询,生成Schema

schemaComposer.Query.addFields({
  userById: UserTC.getResolver('findById'),
  challengeById: ChallengeTC.getResolver('findById')
});

export const gqlSchema = schemaComposer.buildSchema();

4. GQL查询示例

查询指定用户的所有挑战详情

query GetUserChallenges($userId: MongoID!) {
  userById(_id: $userId) {
    _id
    name
    email
    challengeList {
      _id
      task
      description
      createdAt
    }
  }
}

查询指定挑战关联的所有用户

query GetChallengeUsers($challengeId: MongoID!) {
  challengeById(_id: $challengeId) {
    _id
    task
    description
    userList {
      _id
      name
      email
    }
  }
}

创建关联用户的挑战

mutation AddNewChallenge($userId: MongoID!, $task: String!, $desc: String!) {
  createChallengeBindUser(userId: $userId, task: $task, description: $desc) {
    _id
    task
  }
}

内容的提问来源于stack exchange,提问作者Prabhat Mishra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 23:36:03