GraphQL代码中的Javascript循环依赖

时间:2016-04-29 10:07:39

标签: javascript circular-dependency graphql

我是Javascript的新手,并且不知道如何解决这个问题。我正在创建一个GraphQL服务来为数据库提供查询,我想定义三种类型:Person,Company和Relationship

type Relation: {
  person: Person
  company: Company
}

type Person: {
  relationship: Relation
}

type Company: {
  relationship: Relation
}

正如你所看到的,它们是相互依赖的,我会得到人和公司undefined,有没有办法解决这个问题?

数据库架构:

// -------------------- Object(company) --------------------
objectType = new GraphQLObjectType ({
  name: 'Object',
  description: 'Object could be a Company, FinancialOrg, Person or Product.',
  fields: {
    id: {
      type: new GraphQLNonNull(GraphQLString),
    },
    entity_type: {
      type: new GraphQLNonNull(GraphQLString),
      description: 'could be Company, FinancialOrg, Person or Product.'
    },
    entity_id: {
      type: new GraphQLNonNull(GraphQLInt),
    },
    parent_id: {
      type: GraphQLString,
    },
    name: {
      type: new GraphQLNonNull(GraphQLString),
    },
    normalized_name: {
      type: new GraphQLNonNull(GraphQLString),
    },
    permalink: {
      type: new GraphQLNonNull(GraphQLString),
    }
  },
  resolveType: function(object) {
    return dbHandler.findObjectById(object.id);
  }
})

// -------------------- Relationship --------------------
var relationshipType = new GraphQLObjectType({
  name: 'Relationship',
  description: 'Describe the relationship between a person and a object(Corporation, fund)',
  fields: {
    id: {
      type: new GraphQLNonNull(GraphQLInt),
    },
    relationship_id: {
      type: new GraphQLNonNull(GraphQLInt),
    },
    person_object_id: {
      type: new GraphQLNonNull(GraphQLString),
    },
    relationship_object_id: {
      type: new GraphQLNonNull(GraphQLString),
      description: 'A Corporation or a Fund',
    },
  }
});

// -------------------- Person Type --------------------
personType = new GraphQLObjectType ({
  name: 'Person',
  fields: {
    id: {
      type: new GraphQLNonNull(GraphQLInt),
    },
    object_id: {
      type: new GraphQLNonNull(GraphQLString),
    },
    first_name: {
      type: new GraphQLNonNull(GraphQLString),
    },
    last_name: {
      type: new GraphQLNonNull(GraphQLString),
    },
    birthplace: {
      type: GraphQLString
    },
    affiliation_name: {
      type: GraphQLString
    },
  },
});

2 个答案:

答案 0 :(得分:3)

通常,您不会定义特殊的关系类型。在GraphQL中,类型之间的关系在类型本身中定义。

例如,在您的personType中,您可以拥有一个名为companies的字段,该字段可解析为该人所属的公司列表(companyType)。在companyType中,您可以类似地定义要解析为people列表的字段personType

这将基本上为您提供这两种类型之间的多对多关系,这听起来像是在数据库中定义的。

此样式中的personType可能如下所示:

personType = new GraphQLObjectType ({
  name: 'Person',
  fields: () => ({
    id: {
      type: new GraphQLNonNull(GraphQLInt),
    },
    companies: {
      type: new GraphQLList(companyType),
      resolve: person => dbHandler.getAssociatedCompanies(person.id),
      },
    },
  }),
});

至于循环依赖问题,请注意上面的内容,而不是使用fields的对象文字,而是使用一个返回对象的函数,这不会导致任何问题(虽然你的linter可能会抱怨)。

我肯定会建议您阅读GraphQL Types,并确保为您的字段选择了合适的类型。一旦你足够舒服,你肯定想要调查GraphQLInterfaceType,这允许你定义其他类型可以实现的公共字段。最终,它可能是分别定义类型并让它们实现接口而不是通用objectType的更好途径。

另请注意,resolveType可能无法完成您的想法。从GraphQL类型:" [resolveType is]一个函数,用于确定在解析字段时实际使用的类型。"您可以看到可以由多种类型组成的GraphQL类型,例如GraphQLInterfaceTypeGraphQLUnionType

Star Wars example帮助我绕过这些东西。

答案 1 :(得分:0)

尝试将GraphQL端点重构为此类

type Person: {
  employers: [Company],
  ...personAttributes
}

type Company: {
  employees: [Person],
  ...companyAttributes
}

在数据库架构中(我猜您正在使用关系数据库),您需要3个表:

  • 公司
  • 关系

This article explains how to model many-to-many relationships like the one you have.

注意:如果一个人一次只能在一家公司工作,那么架构就会简单得多。