亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

gqlgen go,通過添加一個解析器減少數據庫調用

gqlgen go,通過添加一個解析器減少數據庫調用

Go
烙印99 2022-12-05 17:17:56
我在解決導致性能下降的特定情況時遇到了一些麻煩。我很確定這是可以做到的,但我不知道該怎么做。這是暴露問題的示例模式:type Answer{    answerId: String!    text: String!    topic: Topic!}type Topic {    topicId: String!    name: String!    level: Int!}extend type Query {    answer(answerId: String!): Answer!    answers: [Answer!]! }我遵循了文檔,特別是這部分https://gqlgen.com/getting-started/#dont-eagerly-fetch-the-user 從我的架構中,它生成以下解析器: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調用查詢時,將觸發解析器,它解析屬性并調用解析器。解析器按預期工作,檢索并將其合并到并返回。answerIdanswertextTopicTopicTopicAnswer當answers查詢在沒有answerId參數的情況下被調用時,answer解析器被觸發,它answers通過單個查詢檢索列表。然后,對于該列表的每個元素,它調用Topic解析器。Topic 檢索 a并將其Topic合并到單 例中Answer并返回。結果在這兩種情況下都可以,但是answers如果我要求很多答案,查詢就會成為性能問題。對于每個答案,Topic解析器都會被觸發并執行查詢以檢索單個記錄。前任。如果我有 2 個答案 --> 1 個查詢[Answer0, Answer1],然后 1 個查詢 Topic0和 1 個Topic1前任。10 個答案 --> 1 個[Answer0, ..., Answer9],然后每個 10 個TopicN我想獲得一些topic數組解析器,例如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。有可能嗎?我在哪里可以找到這種方法的例子?謝謝
查看完整描述

1 回答

?
慕蓋茨4494581

TA貢獻1850條經驗 獲得超11個贊

可以使用數據加載器(文檔)解決問題


我必須為以下數據源實現Topics:


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

}



查看完整回答
反對 回復 2022-12-05
  • 1 回答
  • 0 關注
  • 147 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號