I have cases with nested results in JSON. here’s the sample result,
{
"total_result" : 25,
"questions" : [
{
"id" : 1,
"text" : "the question of user 1 here",
"user" : {
"id" : 5,
"name" : "user 5",
},
"answers" : [
{
"id" : 5,
"text" : "first answer to user 1 question",
"user" : {
"id" : 10,
"name" : "user 10",
}
},
{
"id" : 6,
"text" : "second answer to user 1 question",
"user" : {
"id" : 11,
"name" : "user 11",
}
},
{
"id" : 10,
"text" : "third answer to user 1 question",
"user" : {
"id" : 12,
"name" : "user 12",
}
}
]
},
{
"id" : 2,
"text" : "the question by user 2 here",
"user" : {
"id" : 6,
"name" : "user 6",
},
"answers" : [
{
"id" : 5,
"text" : "first answer to user 2 question",
"user" : {
"id" : 30,
"name" : "user 30",
}
},
{
"id" : 6,
"text" : "second answer to user 2 question",
"user" : {
"id" : 20,
"name" : "user 20",
}
},
{
"id" : 10,
"text" : "third answer to user 2 question",
"user" : {
"id" : 1,
"name" : "user 1",
}
}
]
},
]
}
my struct goes here,
type Question struct {
Id int
Text string ...
User User ...
Answer []Answer ...
}
type User struct {
Id int ...
Name string ...
}
type Answer struct {
Id int ...
Text string ...
User User ...
}
here’s the query to get questions
and user.Detail
query := "select text, user_id from questions limit 10 offset 10"
rows, err, := db.QueryCtx(ctx, query)
//handel error
var questions []Question
var userIds []string
for rows.Next() {
var q Question
var userId string
//scan to `question` and `userId`
questions = append(questions, q)
userIds = append(questions, userId)
}
here’s the query to get the user to the question
query = "select name from users where id = any($1)"
userRows, err := db.QueryCtx(ctx, query, pq.Array(userIds))
//handle error
var users []User
//scan and store to users
here’s the query to get answers to the question
query = "select answers.id, answers.text, u.id, u.name from answers join questions as q on q.id=answers.question_id join users as u on u.id=answers.user_id where answers.questions_id=$1"
for i := 0; i < len(questions); i++{
rowAnswer, err := db.QueryCtx(ctx, query, questions[i].Id)
//handle error
var answers []Answer
for rowAnswer.Next(){
var answer Answer
//scan to answer
append = (answers, answer)
}
questions[i].User.Id = users[i].Id
questions[i].User.Name = users[i].Name
questions[i].Answer = answers
}
users
table
id | name |
---|---|
1 | name |
questions
table
id | text | user_id |
---|---|---|
1 | text | 1 |
answers
table
id | text | question_id | user_id |
---|---|---|---|
1 | text | 1 | 1 |
the result is good, nothing wrong with the code and the result. but, I’m thinking about the n+query
case, because I do looping to get the answers. my question is, is it reasonable to do that, or is any good advice for my code?
2
Answers
In get questions, you need var
questionIds
andmapQuestionIdx
where in
so it look like this
On query to get answers to the question
question_id
You can make use of a combination of struct tag and encoding/json to un-marshal your result properly.
Example for your use case:
Redeclare your type as
To unmarshal simply: