如何嵌套查询child的child table数据

How to nest query child's child table data

我有一个多对多 table 调用用户 -> 任务,我可以用这个查询任务:

var user models.User
    DB.Find(&user, "user_addr=?", userAddr)
    //log.Infof("find user: ", user)
    DB.Model(&user).Related(&tasks, "Tasks")

但是,在我的任务中,我有一个子任务 table 是一对多的,称为子任务。我如何将其作为任务中的字段查询出来。这是我的任务结构:

type Tasks struct {
    gorm.Model
    TasksID int `json:"tasks_id"`
    // TasksCreateTime is the hash value since it is unique
    //TasksHash string `json:"tasks_hash"`
    // tasks related fields
    TasksTitle string `json:"tasks_title"`
    TasksCreateTime time.Time `json:"tasks_create_time"`
    TasksComment string `json:"tasks_comment"`
    SubTasks []SubTask `json:"sub_tasks" gorm:"foreignkey:ID"`
}

我想查询出数据并将其分配给 SubTasks 字段。

如何嵌套?

这种方式行得通吗?

func FetchSyncTasksForUser(userAddr string, tasks *[]models.Tasks) {
    log.Infof("fetch sync tasks for user %s ", userAddr)
    var user models.User
    DB.Find(&user, "user_addr=?", userAddr)
    DB.Preload("Tasks").Preload("Tasks.SubTasks").Find(&user, "user_addr = ?", userAddr)
    tasks = &user.Tasks
}

您是否尝试过 gorm 预加载功能?我将预加载必要模型的代码片段放在一起。它会将格式化后的模型打印到命令行。

更新:包括一个片段以通过 ID 查找用户 https://gorm.io/docs/query.html

package main

import (
    "encoding/json"
    "fmt"
    "gorm.io/driver/sqlite"
    "gorm.io/gorm"
)

type User struct {
    gorm.Model
    Name  string
    Tasks []Task
}

type Task struct {
    gorm.Model
    UserId   uint
    SubTasks []SubTask
}

type SubTask struct {
    gorm.Model
    TaskId uint
}

func main() {
    db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
    if err != nil {
        panic("failed to connect database")
    }

    // Migrate the schema
    db.AutoMigrate(&User{}, &Task{}, &SubTask{})

    // Create
    user := User{Name: "C"}
    db.Create(&user)

    task := Task{UserId: user.ID}
    db.Create(&task)

    subTaskOne := SubTask{TaskId: task.ID}
    subTaskTwo := SubTask{TaskId: task.ID}
    db.Create(&subTaskOne)
    db.Create(&subTaskTwo)

    // Find all users, with tasks and subtasks
    users := make([]User, 1)
    db.Preload("Tasks").Preload("Tasks.SubTasks").Find(&users)

    for _, u := range users {
        jsonOutput, err := json.MarshalIndent(u, "", "  ")
        if err != nil {
            panic("")
        }
        fmt.Println(string(jsonOutput))
    }

    // Find only one user by user_addr with tasks and subtasks

    oneUser := User{}
    db.Where("user_addr = ?", user.UserAddr).Preload("Tasks").Preload("Tasks.SubTasks").First(&oneUser)

    jsonOutput, err := json.MarshalIndent(oneUser, "", "  ")
    if err != nil {
        panic("")
    }
    fmt.Println(string(jsonOutput))

    // Clean up
    db.Delete(&subTaskTwo)
    db.Delete(&subTaskOne)
    db.Delete(&task)
    db.Delete(&user)
}