Javascript GraphQL 代码中的循环依赖
Javascript circular dependency in GraphQL code
我是 Javascript 的新手,不知道如何解决这个问题。我正在创建一个 GraphQL 服务来提供对数据库的查询,我想定义三种类型:Person、Company 和 Relationship
type Relation: {
person: Person
company: Company
}
type Person: {
relationship: Relation
}
type Company: {
relationship: Relation
}
如你所见,他们是相互依存的,我会得到 Person 和 Company 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
},
},
});
尝试将您的 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.
注意:如果一个人一次只能在一家公司工作,架构就简单多了。
通常您不会定义特殊的关系类型。在 GraphQL 中,类型之间的关系在类型本身中定义。
例如,在您的 personType
中,您可以有一个名为 companies
的字段,它解析为该人所属的公司列表 (companyType
s)。在您的 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
使用对象文字,您可以使用 returns 对象的函数,这不会导致任何问题(尽管你的 linter 可能会抱怨)。
我肯定会建议通读 GraphQL Types 并确保您已为您的字段选择了合适的类型。一旦你足够舒服,你肯定会想研究 GraphQLInterfaceType
,它允许你定义其他类型可以实现的公共字段。最终,单独定义类型并让它们实现接口而不是使用通用 objectType
.
可能是更好的途径
另请注意,resolveType
可能并不像您认为的那样。来自 GraphQL 类型:“[resolveType 是] 一个函数,用于确定解析字段时实际使用的类型。”您会看到在 GraphQL 类型上可以由多种类型组成,例如 GraphQLInterfaceType
和 GraphQLUnionType
.
Star Wars example 帮助我解决了这些问题。
我是 Javascript 的新手,不知道如何解决这个问题。我正在创建一个 GraphQL 服务来提供对数据库的查询,我想定义三种类型:Person、Company 和 Relationship
type Relation: {
person: Person
company: Company
}
type Person: {
relationship: Relation
}
type Company: {
relationship: Relation
}
如你所见,他们是相互依存的,我会得到 Person 和 Company 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
},
},
});
尝试将您的 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.
注意:如果一个人一次只能在一家公司工作,架构就简单多了。
通常您不会定义特殊的关系类型。在 GraphQL 中,类型之间的关系在类型本身中定义。
例如,在您的 personType
中,您可以有一个名为 companies
的字段,它解析为该人所属的公司列表 (companyType
s)。在您的 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
使用对象文字,您可以使用 returns 对象的函数,这不会导致任何问题(尽管你的 linter 可能会抱怨)。
我肯定会建议通读 GraphQL Types 并确保您已为您的字段选择了合适的类型。一旦你足够舒服,你肯定会想研究 GraphQLInterfaceType
,它允许你定义其他类型可以实现的公共字段。最终,单独定义类型并让它们实现接口而不是使用通用 objectType
.
另请注意,resolveType
可能并不像您认为的那样。来自 GraphQL 类型:“[resolveType 是] 一个函数,用于确定解析字段时实际使用的类型。”您会看到在 GraphQL 类型上可以由多种类型组成,例如 GraphQLInterfaceType
和 GraphQLUnionType
.
Star Wars example 帮助我解决了这些问题。