GraphQL突变为嵌套响应返回null

GraphQL突变为嵌套响应返回null,graphql,sequelize.js,apollo,Graphql,Sequelize.js,Apollo,我有两种型号,公司和用户。从数据库的角度来看,一家公司有很多用户。在创建单个用户时,我希望通过返回与该用户关联的公司来利用graphQL的强大功能。但是,这仅在执行查询时有效。尝试变异时,对象会发生变异,但请求的关系数据始终返回null 在模型中,我们声明了一个一->多关系,并将公司模型模式包括在我们的用户模型模式中以访问数据 用户模型模式 type User { clients: [Client!] company: Company <-------

我有两种型号,公司和用户。从数据库的角度来看,一家公司有很多用户。在创建单个用户时,我希望通过返回与该用户关联的公司来利用graphQL的强大功能。但是,这仅在执行查询时有效。尝试变异时,对象会发生变异,但请求的关系数据始终返回null

在模型中,我们声明了一个一->多关系,并将公司模型模式包括在我们的用户模型模式中以访问数据

用户模型模式

  type User {
    clients: [Client!]
    company: Company         <------- Company Relation
    companyId: UUID
    confirmed: Boolean
    defaultPortfolioSize: Int
    email: String!
    firstName: String!
    lastLogin: String!
    lastName: String!
    id: UUID!
    isActive: Boolean
    isStaff: Boolean
    isSuperuser: Boolean
    password: String
    phoneNumber: String
    priceNotification: Boolean
    priceThreshold: Float
    sentimentNotification: Boolean
    sentimentThreshold: Float
    token: String

    clientCount: Int
    notificationCount: Int
    portfolioCount: Int
    stockAverageCount: Float
    totalValue: Float
    stockList: [PortfolioStock!]
  }
数据加载器是魔法发生的地方。我们调用upsertUser来创建、更新和删除任何对象。在这里,我们成功地创建了一个用户,并可以在db中验证创建过程

用户数据加载器

upsertUser: async (user, params) => {
    ...

    /* Register  */

    if (!params.companyId) {
      throw new UserInputError("Missing 'companyId' parameter");
    }

    if (!params.password) {
      throw new UserInputError("Missing 'password' parameter");
    }

    let newUser = new User({
      billingAddressId: 0,
      dateJoined: new Date(),
      defaultPortfolioSize: 45,
      isActive: true,
      isStaff: false,
      isSuperuser: false,
      lastLogin: new Date(),
      phoneNumber: '',
      priceNotification: false,
      priceThreshold: 0,
      sentimentNotification: false,
      sentimentThreshold: 0,
      subscriptionStatus: false,
      ...params,
    });

    newUser = await newUser.save();
    newUser.token = getJWT(newUser.email, newUser.id);

    EmailManager(
      EmailTemplate.CONFIRM_ACCOUNT,
      `${config.emailBaseUrl}authentication/account-confirmation/?key=${
        newUser.token
      }`,
      newUser.email
    );

    return newUser;
  },

  // Including the users query dataloader for reference
  users: async params => {
    return await User.findAll(get({ ...defaultParams(), ...params }));
  },
下面是一个示例,我们创建了一个用户对象,并使用嵌套的公司关系请求响应

示例突变

mutation {
  user(
    companyId: "16a94e71-d023-4332-8263-3feacf1ad4dc",
    firstName: "Test"
    lastName: "User"
    email: "test@gmail.com"
    password: "PleaseWork"
  ) {
    id
    company {
      id
      name
    }
    email
    firstName
    lastName
  }
}
但是,当请求将关系包括在响应对象中时,api返回null而不是对象

示例响应

ACTUAL:
{
  "data": {
    "user": {
      "id": "16a94e71-d023-4332-8263-3feacf1ad4dc",
      "company": null,
      "email": "test@gmail.com",
      "firstName": "Test",
      "lastName": "User"
    }
  }
}

EXPECTED:
{
  "data": {
    "user": {
      "id": "16a94e71-d023-4332-8263-3feacf1ad4dc",
      "company": {
        "id": "16a94e71-d023-4332-8263-3feacf1ad4dc",
        "name": "Test Company",
      },
      "email": "test@gmail.com",
      "firstName": "Test",
      "lastName": "User"
    }
  }
}

我想我有点困惑,为什么graphQL不能在突变期间对我的嵌套对象进行图形化,但可以通过查询进行图形化。

问题在于Sequelize。由于表的突变不与其关联共享,因此突变对象不像典型查询那样包含所述关联。因此,从变异对象请求的任何关联都将返回null,因为该对象不直接存在于模型中

也就是说,有几种方法可以补充这个问题

  • 创建-插入新行时,可以特别包括与Sequelize的创建或构建方法的关联。像这样:
  • 使用方法中的options参数,我们可以通过关联的模型传递include参数。这将与关联一起返回

  • 更新-这个有点棘手,因为关联不在正在变异的模型中。因此,返回的对象将不包含这些关联。此外,Sequelize的更新方法没有像我们第一次创建对象时那样提供包含模型关联的选项。下面是一个快速解决方案:
  • 首先,我们使用update方法来改变对象。更新后,我们使用findOne方法获取具有关联的变异对象

    虽然这解决了问题,但肯定还有其他方法。
    特别是,如果您想通过此模型直接改变这些关联。如果是这样的话,我建议查看Sequelize。

    问题在于Sequelize。由于表的突变不与其关联共享,因此突变对象不像典型查询那样包含所述关联。因此,从变异对象请求的任何关联都将返回null,因为该对象不直接存在于模型中

    也就是说,有几种方法可以补充这个问题

  • 创建-插入新行时,可以特别包括与Sequelize的创建或构建方法的关联。像这样:
  • 使用方法中的options参数,我们可以通过关联的模型传递include参数。这将与关联一起返回

  • 更新-这个有点棘手,因为关联不在正在变异的模型中。因此,返回的对象将不包含这些关联。此外,Sequelize的更新方法没有像我们第一次创建对象时那样提供包含模型关联的选项。下面是一个快速解决方案:
  • 首先,我们使用update方法来改变对象。更新后,我们使用findOne方法获取具有关联的变异对象

    虽然这解决了问题,但肯定还有其他方法。
    特别是,如果您想通过此模型直接改变这些关联。如果是这样的话,我建议查看Sequelize的。

    Daniel Reardan可能会通过他的解释链接回答这个问题:。我了解到GraphQL消息非常普遍,问题可能是许多问题之一。最好从Daniel的解决方案开始。@Preston感谢您的回复,我会检查它。如果您说您在查询时成功检索到了公司信息。如何检索给定用户的公司数据?如果您使用标准的DB连接进行此操作,则您的
    新用户
    数据可能不完整,并且不包含
    公司
    信息。理想情况下,您希望在
    用户
    类型上为
    公司
    字段指定一个特定的解析器,并以这种方式实现您的关联;这将保证无论何时您返回类型
    用户
    (当然,如果查询了
    公司
    字段),解析程序都将始终运行。Daniel Reardan可能会通过其解释的链接回答此问题:。我了解到GraphQL消息非常普遍,问题可能是许多问题之一。最好从Daniel的解决方案开始。@Preston感谢您的回复,我会检查它。如果您说您在查询时成功检索到了公司信息。如何检索给定用户的公司数据?如果您使用标准的DB连接进行此操作,则您的
    新用户
    数据可能不完整,并且不包含
    公司
    信息。理想情况下,您希望在
    用户
    类型上为
    公司
    字段指定一个特定的解析器,并以这种方式实现您的关联;这将保证无论何时返回类型
    用户
    (当然,如果查询了
    公司
    字段),解析程序都将始终运行。
    mutation {
      user(
        companyId: "16a94e71-d023-4332-8263-3feacf1ad4dc",
        firstName: "Test"
        lastName: "User"
        email: "test@gmail.com"
        password: "PleaseWork"
      ) {
        id
        company {
          id
          name
        }
        email
        firstName
        lastName
      }
    }
    
    ACTUAL:
    {
      "data": {
        "user": {
          "id": "16a94e71-d023-4332-8263-3feacf1ad4dc",
          "company": null,
          "email": "test@gmail.com",
          "firstName": "Test",
          "lastName": "User"
        }
      }
    }
    
    EXPECTED:
    {
      "data": {
        "user": {
          "id": "16a94e71-d023-4332-8263-3feacf1ad4dc",
          "company": {
            "id": "16a94e71-d023-4332-8263-3feacf1ad4dc",
            "name": "Test Company",
          },
          "email": "test@gmail.com",
          "firstName": "Test",
          "lastName": "User"
        }
      }
    }
    
    let client = new Client(
          {
            ...params
          },
          { include: [ClientGroup] }
        );
    
    return client.save()
    
    await Client.update(params, {
              // @ts-ignore: Unknown property 'plain'
              plain: true,
              returning: true,
              where: { id: params.id },
            });
    
            return await Client.findOne({
              include: [ClientGroup],
              where: { id: params.id },
            });