在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
欄位具有:
從 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中文網其他相關文章!