是否可以使用 Graphql 和 Sequelize 进行多租户?
Posted
技术标签:
【中文标题】是否可以使用 Graphql 和 Sequelize 进行多租户?【英文标题】:Is it possible to do a multi tenancy with Graphql and Sequelize? 【发布时间】:2019-09-18 16:14:18 【问题描述】:强调文本我有一个关于 GraphQl 和多租户的相当棘手的问题。
假设有 3 个表,OWNER、HOUSE 和 TENANTS。我将在 Sequelize 和 GraphQl 伪代码中描述它们:
Owner 表(有多个房屋和多个租户)
const OWNER = sequelize.define('owner',
ownerId: type: Sequelize.INTEGER,
name: type: Sequelize.STRING
OWNER.associate = models =>
models.owner.hasMany(models.house, foreignKey: name: 'ownerId', field: 'ownerId')
models.owner.hasMany(models.tenant, foreignKey: name: 'ownerId', field: 'ownerId')
房屋表(属于所有者,有多个租户)
const HOUSE = sequelize.define('house',
houseId: type: Sequelize.INTEGER,
ownerId: type: Sequelize.INTEGER,
name: type: Sequelize.STRING
HOUSE.associate = models =>
models.house.belongsTo(models.owner, foreignKey: name: 'ownerId', field: 'ownerId')
models.house.hasMany(models.tenant, foreignKey: name: 'houseId', field: 'houseId')
租户表(属于业主和房屋)
const TENANT = sequelize.define('tenant',
tenantId: type: Sequelize.INTEGER,
ownerId: type: Sequelize.INTEGER,
houseId: type: Sequelize.INTEGER,
name: type: Sequelize.STRING
TENANT.associate = models =>
models.tenant.belongsTo(models.owner, foreignKey: name: 'ownerId', field: 'ownerId')
models.tenant.belongsTo(models.house, foreignKey: name: 'houseId', field: 'houseId')
拥有者 graphql 对象
const OwnerType = new GraphQLObjectType(
name: 'Owner',
fields: () => (
ownerId: type: GraphQLInt ,
name: type: GraphQLString ,
houses:
type: GraphQLList(HouseType),
resolve(owner)
return owner.getHouse()
,
houseById:
type: HouseType,
args: <args is not defined>
resolve(owner)
return <???>
,
)
)
以下是一些简单的 GraphQL 查询:
ownerById =
type: OwnerType,
args:
ownerId: type: GraphQLInt ,
,
resolve(parents, args)
return models.owner.findOne( where: args )
houses =
type: GraphQLList(HouseType),
resolve(parents, args)
return models.house.findAll()
houseById =
type: HouseType,
args:
houseId: type: GraphQLInt ,
,
resolve(parents, args)
return models.house.findOne( where: args )
tenants =
type: GraphQLList(TenantType),
resolve(parents, args)
return models.tenant.findAll()
这些客户端查询有效:
ownerById(ownerId: 1)
ownerId
name
house
houseId
name
houseById(houseId: 2)
houseId
name
tenant
tenantId
name
我需要让多租户工作是这样的:
ownerById(ownerId: 1)
ownerId
name
houseById(houseId: 2)
houseId
name
tenant
tenantId
name
有没有办法存档这个或者超出 GraphQl 可以做什么的范围?
如果是,graphql 对象houseById
查询是什么样的?
提前致谢。
【问题讨论】:
目前尚不清楚您对houseById(ownerId: 2)
的要求是什么,至少在您描述的数据模型的上下文中是这样。 Owner 和 House 之间存在一对多的关系。通过 id (ownerById(ownerId: 1)
) 获取 Owner 节点后,该节点的任何字段都将与该特定节点相关。因此,我不确定您通过允许消费者为其中一个字段指定不同的ownerId
来尝试做什么。你能澄清你的问题吗?
你是在问如何构造一个包含多个查询的请求吗?或者您是在问如何通过一个或多个任意参数过滤“嵌套”(即非根)字段?还是完全不同的东西?
对不起@DanielRearden ownerId
应该说houseId
。我的坏...
【参考方案1】:
除非我遗漏了什么,否则houseById
的解析器似乎与同一类型的 houses
字段的解析器没有太大区别。
houseById:
type: HouseType,
args:
houseId: type: GraphQLInt ,
,
async resolve(owner, houseId )
const houses = await owner.getHouses( where: id: houseId )
return houses[0]
,
对于HasMany
关联,目标模型的getter 解析为实例数组。所以我们需要先获取该数组,然后只返回其中的第一项,因为我们的字段表示单个对象而不是列表。如果不想使用 async/await,也可以这样做:
return owner.getHouses( where: id: houseId )
.then(houses => houses[0])
还值得一提的是,这种模式的模式违反了约定。与其拥有houses
字段、houseById
字段、houseBySomeOtherArg
字段等,不如考虑公开一个带有一个或多个参数的houses
字段,例如id
、name
或您的任何过滤条件想提供。然后,您的字段可以根据传入的任何参数过滤房屋,或者如果没有提供过滤器参数,则返回所有结果。
【讨论】:
嗨丹尼尔,你是对的。我只是忘记了resolve()
函数中的args
参数。最后我的现场道具看起来有点不同。我没有传递 owner
并使用 getHouses()
函数,而是导入了 Sequelize models
并像这样使用了 findOne()
函数:resolve(owner, args) return models.house.findOne( where: args )
以上是关于是否可以使用 Graphql 和 Sequelize 进行多租户?的主要内容,如果未能解决你的问题,请参考以下文章
是否可以从 Relay 突变访问 GraphQL 验证错误?