如何在没有`include`的情况下使用graphql-sequelize急切加载关联?

时间:2018-03-16 21:43:53

标签: sequelize.js graphql apollo-server

我使用graphql-sequelize来实现GraphQL端点。我刚刚创建了一个新的辅助实体并将其与我的一个主要实体相关联,现在我正在尝试在获取主要实体时包含相关的辅助实体。当我尝试实现该提取时,我收到以下错误:

AssertionError ERR_ASSERTION Include support has been removed in favor of dataloader batching

我的旧的基于解析器的gql端点看起来像这样:

driver: {
    type: MyGQLTypes.Driver,
    resolve: resolver(Driver)
}

我从代码库中其他地方的实验中了解到这通常有效:

const driver = Driver.getById(`${uuid}`, {
    include: { model: Helmet }
})
// yields:
// {
//     id: '<uuid>',
//     name: 'Tom',
//     helmetNumber: '470',
//     Helmet: {
//         number: '470',
//         type: 'cool',
//         color: 'red'
//     }
// }

因此,在检查source code of graphql-sequelize's resolver并确定第二个参数传递给sqlz访问器之后,我将相同的include添加到我的GQL解析器中,如下所示:

driver: {
    type: MyGQLTypes.Driver,
    resolve: resolver(Driver, {
        include: { model: Helmet }
    })
}

当我得到致命的错误时。研究表明,graphql-sequelize人员现在不允许performance reasons使用a cryptic comment,而是支持sequelize的数据加载器,我目前没有使用它,也没有计划使用。

但即使我这样,也没有回答他们希望我们如何在include内获取相关行的问题。我发现http://sqlfiddle.com/#!9/649ef3/1表示有一个名为resolver的替代品,但我还没有能够找到它的文档,而且从臀部开始射击失败了:

join

我所能想到的就是添加一个driver: { type: MyGQLTypes.Driver, resolve: resolver(Driver, { include: { model: Helmet } // fatal error: disallowed join: { model: Helmet } // no effect, no error join: Helmet // no effect, no error }) } 例程来手动获取相关模型,然后将该结果附加到主模型中,如果以标准方式获取它,它将出现在同一个地方(即使用after),如下所示:

include

当代码执行并找到我期望的模型时,它无法将找到的模型附加到同一个地方。

Sqlz实例不是普通哈希:它们具有driver: { type: MyGQLTypes.Driver, resolve: resolver(Driver, { // can't do this: include: { model: Helmet } // so I try to emulate it this way: after: async (driver) => { driver.Helmet = await driver.getHelmet() return driver } }) } 属性,其中包含数据库中的原始列值,当您引用dataValues时,隐藏的getter从{{1}获取值}。实验表明,通过myModel.colName的急切加载会导致相关模型出现在myModel.dataValues[ colName ]结构中,可能与所需的任何隐藏访问器一起出现,如下所示:

include

我很确定我可以在那里附加获取的模型:

dataValues

但我认为我们应该避免摆弄{ dataValues: { id: '<uuid>', name: 'Tom', helmetNumber: '470', Helmet: { dataValues: { number: '470, type: 'cool', color: 'red' } } } } ,而这似乎是ham骂。

我正在使用driver.dataValues.Helmet = await driver.getHelmet() ,它(正确地)根据GQL架构验证解析器返回值,因此,dataValues的GQL类型定义在技术上是 downstream < / em>这个解析函数。我已经开始为构建GQL类型构建一堆糖(特别是在初级实体中嵌入辅助实体时),这种观点鼓励我认为基于apollo-server-express的端点应该统一 - 形状的回报。即如果某些实体的解析器发出破坏的sqlz模型实例,而其他实体返回健康的实例,则会很糟糕。

我们如何在没有Driver的graphql-sequelize resolver中实现预先加载?

包装版本:

resolver

1 个答案:

答案 0 :(得分:1)

我尝试了两件事:

driver: {
    type: MyGQLTypes.Driver,
    resolve: resolver(Driver, {
        after: driver => {
            return Driver.findById(driver.id, {
                include: [ Helmet ]
            })
        }
    })
}

这样可行,但它会两次击中主表,这是 mega gross。

所以,我决定抛出graphql-sequelize的“helper”resolver,并直接编程到apollo-server-express的API:

driver: {
    type: MyGQLTypes.Driver,
    resolve: (parent, args, context, info) => {
        return Driver.findById(args.id, {
            include: [ Helmet ]
        })
    })
}

像冠军一样工作。可能有一个我还没有看到的缺点。我想时间会证明。

让这个开放一段时间以防其他人有更好的答案(包括我自己)。