go-gorm fragt Multi-Bit-Felder ab

王林
Freigeben: 2024-02-09 20:03:09
nach vorne
656 Leute haben es durchsucht

go-gorm 查询多位字段

In der PHP-Entwicklung sind Datenbankoperationen sehr häufige Aufgaben. Bei Datenbankoperationen ist die Abfrage mehrerer Felder eine häufige Anforderung. Als Reaktion auf diese Nachfrage ist go-gorm eine leistungsstarke ORM-Bibliothek, die Entwicklern dabei helfen kann, mehrere Felder schnell und effizient abzufragen. In diesem Artikel stellt der PHP-Editor Xinyi vor, wie mehrere Felder in go-gorm abgefragt werden, und gibt entsprechenden Beispielcode, der Ihnen hilft, diese Technik leicht zu beherrschen. Ganz gleich, ob Sie Anfänger oder erfahrener Entwickler sind, dieser Artikel kann Ihnen wertvolle Hilfe und Anleitung bieten. Lass uns einen Blick darauf werfen!

Frageninhalt

Ich habe folgende Modelle:

<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>
Nach dem Login kopieren

Wenn Sie ein Geheimnis mit einer oder mehreren Umgebungen erstellen, erstellt die environment_secrets-Tabelle eine oder mehrere Zeilen basierend darauf, wie viele Umgebungen dasselbe Geheimnis teilen:

secret_id | environment_id
--------------------------
uuid      | uuid
Nach dem Login kopieren

Was ich tun möchte, ist das Feld secrets 表中的 environments abzufragen.

Das Problem, das ich habe, ist, dass es während der Preload 将数据插入 environments 字段,但在 Find-Klausel anscheinend nicht verfügbar ist:

<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>
Nach dem Login kopieren

Kurz gesagt, ich versuche, diese Abfrage zu schreiben: 在“secrets”表中,查找拥有这些秘密的匹配 userId,并查看秘密中关联的“environments.id”字段以查找匹配的 UUID特定环境 UUID(它也将由该用户拥有).

Wenn ich zum Beispiel diese 92a4c405-f4f7-44d9-92df-76bd8a9ac3a6 用户 UUID 查询 secrets 以检查所有权,并使用此 cff8d599-3822-474d-a980-fb054fb9 进行查询23ccUmgebungs-UUID verwende, sollte die resultierende Ausgabe so aussehen...

<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>
Nach dem Login kopieren

Gibt es eine JOIN-Abfrage oder vielleicht eine reine SQL-Abfrage, die ich schreiben kann, um sie in environments 行数据在 secrets für die Abfrage verfügbar zu machen?

Die Problemumgehung

ist nicht schön, aber diese grobe GORM-SQL-Abfrage funktioniert wie erwartet:

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 @> ?;
Nach dem Login kopieren

Abfrage kann verstanden werden als...

Aggregieren Sie Geheimnisse in r (结果),其中 environments Feldern mit:

  • Geheime ID, die mit mehreren Paaren geheimer Tabellen-IDs übereinstimmt
  • Mehrtabellen-Umgebungs-ID, die mit der Umgebungs-ID übereinstimmt
  • Und filtern Sie basierend auf der geheimen Benutzer-ID, die mit dem Parameter Benutzer-ID übereinstimmt

Von r (结果)中查找 environments JSON 数组中的部分参数化 id.

Und einige Beispiele für Go-Code mit go Fiber:

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)
}
Nach dem Login kopieren

Das obige ist der detaillierte Inhalt vongo-gorm fragt Multi-Bit-Felder ab. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:stackoverflow.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!