首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >gqlgen go,通过添加一个解析器来减少db调用

gqlgen go,通过添加一个解析器来减少db调用
EN

Stack Overflow用户
提问于 2022-04-26 13:15:24
回答 1查看 485关注 0票数 2

我有一些困难,解决一个特定的情况,导致性能下降。我很确定这是可以做的事,但我不知道该怎么做。

下面是一个暴露问题的示例模式:

代码语言:javascript
复制
type Answer{
    answerId: String!
    text: String!
    topic: Topic!
}

type Topic {
    topicId: String!
    name: String!
    level: Int!
}
代码语言:javascript
复制
extend type Query {
    answer(answerId: String!): Answer!
    answers: [Answer!]! 
}

我遵循了文档,特别是我的模式中的这个部分https://gqlgen.com/getting-started/#dont-eagerly-fetch-the-user,它生成以下解析器:

代码语言:javascript
复制
func (r *queryResolver) Answer(ctx context.Context, answerId string) (*models.Answer, error) {
...
#Single Query which retrives single record of Answer from DB.
#Fills a model Answer with the Id and the text
#Proceeds by calling the Topic resolver
...
}

func (r *queryResolver) Answers(ctx context.Context) ([]*models.Answer, error) {
...
#Single Query which retrives list of Answers from DB
#Fills a list of model Answer with the Id and the text
-->#For each element of that list, it calls the Topic resolver
...
}


func (r *answerResolver) Topic(ctx context.Context, obj *models.Answer) (*models.Topic, error) {
...
#Single Query which retrives single record of Topic from DB
#Return a model Topic with id, name and level
...
}

当使用answer参数调用answerId查询时,将触发answer解析器,它解析text属性并调用Topic解析器。Topic解析器按预期工作,检索一个Topic,它将其合并到Answer中并返回。

answers查询在没有answerId参数的情况下被调用时,answer解析器就会被触发,它用一个查询来检索answers列表。然后,对于该列表的每个元素,它调用Topic解析器。Topic检索一个Topic,并将其合并到单个Answer中并返回。

结果在这两种情况下都是可以的,但是如果我想要很多答案的话,answers查询就会成为一个性能问题。对于每个答案,Topic解析器将被触发并执行一个查询,以检索单个记录。

例如。如果我有两个答案->一个查询[Answer0, Answer1],然后一个查询Topic0,一个查询Topic1

例如。10个答案-- [Answer0, ..., Answer9] >1,每个TopicN > 10

我想获得一些topic数组解析器,如

代码语言:javascript
复制
func (r *answersResolver) Topics(ctx context.Context, obj *[]models.Answer) (*[]models.Topic, error) {
...
#Single Query which retrives list of Topics from DB
#Return a list of model Topic with id, name and level
...
}

我期望返回数组的每个元素都与Answers数组的对应元素合并。

在某种程度上是可能的吗?我在哪里可以找到这样的方法的例子?谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-27 18:35:43

这个问题可以用数据采集器(文档)解决。

我必须为Topics实现以下数据源

代码语言:javascript
复制
package dataloader

import (
    "github.com/graph-gophers/dataloader"
)

type ctxKey string

const (
    loadersKey = ctxKey("dataloaders")
)


type TopicReader struct {
    conn *sql.DB
}

func (t *TopicReader) GetTopics(ctx context.Context, keys dataloader.Keys) []*dataloader.Result {
    topicIDs := make([]string, len(keys))
    for ix, key := range keys {
        topicIDs[ix] = key.String()
    }
    res := u.db.Exec(
        r.Conn,
        "SELECT id, name, level
        FROM topics
        WHERE id IN (?" + strings.Repeat(",?", len(topicIDs-1)) + ")",
        topicIDs...,
    )
    defer res.Close()

    output := make([]*dataloader.Result, len(keys))
    for index, _ := range keys {
            output[index] = &dataloader.Result{Data: res[index], Error: nil}
    }
    return output
}

type Loaders struct {
    TopicLoader *dataloader.Loader
}


func NewLoaders(conn *sql.DB) *Loaders {
    topicReader := &TopicReader{conn: conn}
    loaders := &Loaders{
        TopicLoader: dataloader.NewBatchedLoader(t.GetTopics),
    }
    return loaders
}

func Middleware(loaders *Loaders, next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        nextCtx := context.WithValue(r.Context(), loadersKey, loaders)
        r = r.WithContext(nextCtx)
        next.ServeHTTP(w, r)
    })
}

func For(ctx context.Context) *Loaders {
    return ctx.Value(loadersKey).(*Loaders)
}

func GetTopic(ctx context.Context, topicID string) (*model.Topic, error) {
    loaders := For(ctx)
    thunk := loaders.TopicLoader.Load(ctx, dataloader.StringKey(topicID))
    result, err := thunk()
    if err != nil {
        return nil, err
    }
    return result.(*model.Topic), nil
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72014642

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档