首頁 > 後端開發 > Golang > go-gorm 查詢多位字段

go-gorm 查詢多位字段

王林
發布: 2024-02-09 20:03:09
轉載
717 人瀏覽過

go-gorm 查询多位字段

在PHP開發中,資料庫操作是非常常見的任務。而在資料庫操作中,查詢多個欄位是一種常見的需求。針對這項需求,go-gorm是一款強大的ORM庫,可以幫助開發者快速、有效率地查詢多個欄位。在本文中,php小編新一將為大家介紹如何在go-gorm中實作查詢多個字段,並給出對應的範例程式碼,幫助大家輕鬆掌握這項技巧。無論是初學者或有一定經驗的開發者,本文都能為你提供有價值的幫助和指導。一起來看看吧!

問題內容

我有以下型號:

<code>type User struct {
    ID        uuid.UUID `gorm:"type:uuid;default:uuid_generate_v4();primary_key" json:"id"`
    ...
}

type Environment struct {
    ID        uuid.UUID `gorm:"type:uuid;default:uuid_generate_v4();primary_key" json:"id"`
    UserId    uuid.UUID `gorm:"type:uuid" json:"userId"`
    User      User      `gorm:"foreignKey:UserId;references:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-"`
    ...
}

type Secret struct {
    ID           uuid.UUID     `gorm:"type:uuid;default:uuid_generate_v4();primary_key" json:"id"`
    UserId       uuid.UUID     `gorm:"type:uuid" json:"userId"`
    User         User          `gorm:"foreignKey:UserId;references:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-"`
    Environments []Environment `gorm:"many2many:environment_secrets;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"environments"`
    ...
}
</code>
登入後複製

建立具有一個或多個環境的機密時,environment_secrets 表格會根據有多少個環境共用相同的機密來建立一行或多行:

secret_id | environment_id
--------------------------
uuid      | uuid
登入後複製

我想做的是查詢 secrets 表中的 environments 欄位。

我遇到的問題是,雖然 Preload 將資料插入 environments 字段,但在 Find 子句期間它似乎不可用:

<code>var secrets []models.Secret
if err := db.Preload("Environments").Find(&secrets, "user_id=? AND ? @> environments.id", userSessionId, environmentId).Error; err != nil {
  return c.Status(fiber.StatusOK).JSON(
    fiber.Map{"error": err.Error()},
  )
}
// ERROR: missing FROM-clause entry for table "environments" (SQLSTATE 42P01)
</code>
登入後複製

簡而言之,我正在嘗試編寫此查詢:在“secrets”表中,查找擁有這些秘密的匹配userId,並查看秘密中關聯的“environments.id”字段以查找匹配的UUID特定環境UUID(它也將由該使用者擁有)

例如,如果我使用此92a4c405-f4f7-44d9-92df-76bd8a9ac3a6 用戶UUID 查詢secrets 以檢查所有權,並使用此cff8d599-3822-474d a980-fb054fb9 進行查詢23cc環境UUID,那麼結果輸出應該看起來像...

<code>[
    {
        "id": "63f3e041-f6d9-4334-95b4-d850465a588a",
        "userId": "92a4c405-f4f7-44d9-92df-76bd8a9ac3a6", // field to determine ownership by specific user
        "environments": [
            {
                "id": "cff8d599-3822-474d-a980-fb054fb923cc", // field to determine a matching environment UUID
                "userId": "92a4c405-f4f7-44d9-92df-76bd8a9ac3a6", // owned by same user
                "name": "test1",
                "createdAt": "2023-08-24T09:27:14.065237-07:00",
                "updatedAt": "2023-08-24T09:27:14.065237-07:00"
            },
            {
                "id": "65e30501-3bc9-4fbc-8b87-2f4aa57b461f", // this secret happens to also be shared with another environment, however this data should also be included in the results
                "userId": "92a4c405-f4f7-44d9-92df-76bd8a9ac3a6", // owned by same user
                "name": "test2",
                "createdAt": "2023-08-24T12:50:38.73195-07:00",
                "updatedAt": "2023-08-24T12:50:38.73195-07:00"
            }
        ],
        "key": "BAZINGA",
        "value": "JDJhJDEwJHR5VjRWZ3l2VjZIbXJoblhIMU1D",
        "createdAt": "2023-08-24T12:51:05.999483-07:00",
        "updatedAt": "2023-08-24T12:51:05.999483-07:00"
    }
    ...etc
]
</code>
登入後複製

是否有一個 JOIN 查詢或可能是原始 SQL 查詢,我可以編寫以使 environments 行資料在 secrets 中可用以進行查詢?

解決方法

不太漂亮,但是這個原始狗 GORM SQL 查詢按預期工作:

SELECT * 
FROM (
    SELECT 
        s.id,
        s.user_id,
        s.key,
        s.value,
        s.created_at,
        s.updated_at,
        jsonb_agg(envs) as environments
    FROM secrets s
    JOIN environment_secrets es ON s.id = es.secret_id
    JOIN environments envs on es.environment_id = envs.id
    WHERE s.user_id = ?
    GROUP BY s.id
) r
WHERE r.environments @> ?;
登入後複製

查詢可以理解為...

將機密聚合為 r (結果),其中 environments 欄位具有:

  • 與多對錶秘密 ID 相符的秘密 ID
  • 與環境 ID 相符的多表環境 ID
  • #並根據與參數使用者 ID 相符的秘密使用者 ID 進行篩選

r (結果)中找出 environments JSON 陣列中的部分參數化 id

以及一些使用 go Fiber 的範例 Go 程式碼:

import (
    "time"

    "github.com/gofiber/fiber/v2"
    "github.com/google/uuid"
    "gorm.io/datatypes"
)

type SecretResult struct {
    ID           uuid.UUID      `json:"id"`
    UserId       uuid.UUID      `json:"userId"`
    Environments datatypes.JSON `json:"environments"`
    Key          string         `json:"key"`
    Value        []byte         `json:"value"`
    CreatedAt    time.Time      `json:"createdAt"`
    UpdatedAt    time.Time      `json:"updatedAt"`
}

func Example(c *fiber.Ctx) error {
    db := database.ConnectToDB();
    userSessionId := c.Locals("userSessionId").(uuid.UUID)

    parsedEnvId, err := uuid.Parse(c.Params("id"))
    if err != nil {
        return c.Status(fiber.StatusBadRequest).JSON(
            fiber.Map{"error": "You must provide a valid environment id!"},
        )
    }

    var secrets []SecretResult
    if err := db.Raw(`
       USE SQL QUERY MENTIONED ABOVE
    `, userSessionId,`[{"id":"`+parsedEnvId.String()+`"}]`),
    ).Scan(&secrets).Error; err != nil {
        fmt.Printf("Failed to load secrets with %s: %s", parsedEnvId, err.Error())
        return c.Status(fiber.StatusInternalServerError).JSON(
            fiber.Map{"error": "Failed to locate any secrets with that id."},
        )
    }

    return c.Status(fiber.StatusOK).JSON(secrets)
}
登入後複製

以上是go-gorm 查詢多位字段的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:stackoverflow.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板