使用Go语言中的go-pg库正确访问PostgreSQL数据库的方法是什么?

huangapple go评论73阅读模式
英文:

Correct way to access data from postgresql using go-pgsql in GoLang

问题

我一直在阅读GoLang go-pgsql的文档,以便弄清楚如何访问具有嵌套对象的数据,但是到目前为止我一直没有成功。

这是我想要实现的描述:

我有两个模型ClimateQuestionsSteps

type ClimateQuestions struct {
	tableName struct{} `pg:"climatequestions"`
	Id        int      `json:"id" pg:",pk"`
	Title     string   `json:"title"`
	Steps     []*Steps  `pg:"rel:has-many"`
}

type Steps struct {
	tableName        struct{}          `pg:"steps"`
	Id               int               `json:"id"`
	Label            string            `json:"label"`
	Number           int               `json:"number"`
	QuestionId       int               `json:"question_id"`
}

它们在数据库中的定义如下:

CREATE TABLE climatequestions (
    id SERIAL PRIMARY KEY,
    title VARCHAR(255) NOT NULL
);

CREATE TABLE steps (
    id SERIAL PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    value DOUBLE PRECISION NOT NULL,
    question_id INT REFERENCES climatequestions(id)
);

这两个模型之间的关系是:对于每个气候问题,可以有多个步骤。我通过在ClimateQuestions结构体中添加了一个名为Steps的字段,并使用rel:has-many来表示这一点。

现在,我想从数据库中获取所有的气候问题,并在每个问题中获取一个步骤数据数组。

我尝试的第一种方法是:

var climateQuestions []model.ClimateQuestions
err := db.Model(&climateQuestions).Select()

这部分工作正常,它返回了与气候问题相关的所有数据,但是它没有添加嵌套的步骤数据。以下是返回结果的JSON格式:

[{"id":1,"title":"first question?","Steps":null},{"id":2,"title":"second question?","Steps":null}]

有什么想法可以实现这个需求吗?

英文:

I've been reading the GoLang go-pgsql documentation in order to figure out how to access data with nested objects, but I have so far been unsuccessful.

Here's the description of what I am trying to achieve:

I have two models ClimateQuestions and Steps:

type ClimateQuestions struct {
	tableName struct{} `pg:"climatequestions"`
	Id        int      `json:"id" pg:",pk"`
	Title     string   `json:"title"`
	Steps     []*Steps  `pg:"rel:has-many"`
}

type Steps struct {
	tableName        struct{}          `pg:"steps"`
	Id               int               `json:"id"`
	Label            string            `json:"label"`
	Number           int               `json:"number"`
	QuestionId       int               `json:"question_id"`
}

and here is how they're defined in the database:

CREATE TABLE climatequestions (
    id SERIAL PRIMARY KEY,
    title VARCHAR(255) NOT NULL
);

CREATE TABLE steps (
    id SERIAL PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    value DOUBLE PRECISION NOT NULL,
    question_id INT REFERENCES climatequestions(id)
);

And a relationship between these models is this: For every climate question, there can be many steps. I have denoted this by adding a field in ClimateQuestions struct called Steps with rel:has-many.

Now, from the database, I would like to obtain all the climate questions, and within each of them, I want an array of steps data.

My first method to achieve this has been the following:

var climateQuestions []model.ClimateQuestions
err := db.Model(&climateQuestions).Select()

This partially works in that it returns all the data relevant for climate questions, but it does not add the nested steps data. Here is the JSON format of what is returned:

[{"id":1,"title":"first question?","Steps":null},{"id":2,"title":"second question?","Steps":null}]

Any ideas as to how I may achieve this?

答案1

得分: 1

因为你有自定义的连接外键,所以你需要在ClimateQuestions.Steps中添加标签pg:"rel:has-many,join_fk:question_id"

Steps结构体中,你需要告诉pg它是哪个字段。

你忘记调用Relation函数了。

这是正确的结构体:

type ClimateQuestions struct {
	tableName struct{} `pg:"climatequestions"`
	Id        int      `json:"id" pg:",pk"`
	Title     string   `json:"title"`
	Steps     []*Steps `pg:"rel:has-many,join_fk:question_id"`
}

type Steps struct {
	tableName  struct{} `pg:"steps"`
	Id         int      `json:"id"`
	Label      string   `json:"label" pg:"title"`
	Number     int      `json:"number" pg:"value"`
	QuestionId int      `json:"question_id"`
}

这是你应该执行数据库操作的方式:

var climateQuestions []ClimateQuestions
err := db.Model(&climateQuestions).Relation("Steps").Select()
if err != nil {
    panic(err.Error())
}

for _, v := range climateQuestions {
    fmt.Printf("%#v\n", v)
    for _, v1 := range v.Steps {
        fmt.Printf("%#v\n", v1)
    }
    fmt.Println("")
}
英文:
  1. Because you have custom join foreign key, you need to add tag pg:"rel:has-many,join_fk:question_id" in ClimateQuestions.Steps
  2. In struct Steps, you need to tell pg which field it is.
  3. You forgot to call Relation function

this is the correct struct

type ClimateQuestions struct {
	tableName struct{} `pg:"climatequestions"`
	Id        int      `json:"id" pg:",pk"`
	Title     string   `json:"title"`
	Steps     []*Steps `pg:"rel:has-many,join_fk:question_id"`
}

type Steps struct {
	tableName  struct{} `pg:"steps"`
	Id         int      `json:"id"`
	Label      string   `json:"label" pg:"title"`
	Number     int      `json:"number" pg:"value"`
	QuestionId int      `json:"question_id"`
}


this is how you should exec db.

	var climateQuestions []ClimateQuestions
	err := db.Model(&climateQuestions).Relation("Steps").Select()
	if err != nil {
		panic(err.Error())
	}

	for _, v := range climateQuestions {
		fmt.Printf("%#v\n", v)
		for _, v1 := range v.Steps {
			fmt.Printf("%#v\n", v1)
		}
		fmt.Println("")
	}

huangapple
  • 本文由 发表于 2022年2月27日 03:55:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/71279864.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定