Rumah >pembangunan bahagian belakang >Golang >Menambah parameter pertanyaan penapis dalam Go Huma

Menambah parameter pertanyaan penapis dalam Go Huma

Patricia Arquette
Patricia Arquetteasal
2024-12-07 04:38:16709semak imbas

Daripada apa yang saya dapat ketahui, Huma malangnya tidak menyokong penapis pertanyaan tatasusunan seperti ini: filters[]=filter1&filters[]=filter2 (tidak meninggalkan tanda kurung, mis. filter=filter1&filter=filter2). Saya terjumpa isu Github ini yang memberikan contoh pemisahan penapis dengan koma https://github.com/danielgtaylor/huma/issues/325, jadi itulah yang akhirnya kami lakukan: filters=postcode:eq:RM7(EX, dicipta:gt:2024-01-01

Mendokumentasikan penapis

Tidak seperti parameter badan, yang boleh ditentukan hanya sebagai struct dan kemudian kedua-duanya disahkan dan dijana dalam dokumentasi, dokumentasi dan pengesahan untuk penapis perlu dilakukan secara berasingan.

Dokumentasi hanya boleh ditambah di bawah atribut perihalan objek Huma.Param (di bawah Operasi):

Parameters: []*huma.Param{{
            Name: "filters",
            In:   "query",
            Description: "Filter properties by various fields. Separate filters by comma.\n\n" +
                "Format: field:operator:value\n\n" +
                "Supported fields:\n" +
                "- postcode (operator: eq)\n" +
                "- created (operators: gt, lt, gte, lte)\n",
            Schema: &huma.Schema{
                Type: "string",
                Items: &huma.Schema{
                    Type:    "string",
                    Pattern: "^[a-zA-Z_]+:(eq|neq|gt|lt|gte|lte):[a-zA-Z0-9-:.]+$",
                },
                Examples: []any{
                    "postcode:eq:RM7 8EX",
                    "created:gt:2024-01-01",
                },
            },
            Required: false,
        }},

Adding filter query parameters in Go Huma

Kami kini boleh mentakrifkan struct PropertyFilterParams kami untuk pengesahan:

type FilterParam struct {
    Field    string
    Operator string
    Value    interface{}
}

type PropertyFilterParams struct {
    Items []FilterParam
}

func (s *PropertyFilterParams) UnmarshalText(text []byte) error {
    equalityFields := []string{"postcode"}
    greaterSmallerFields := []string{}
    dateFields := []string{"created"}

    for _, item := range strings.Split(string(text), ",") {
        filterParam, err := parseAndValidateFilterItem(item, equalityFields, greaterSmallerFields, dateFields)
        if err != nil {
            return err
        }
        s.Items = append(s.Items, filterParam)
    }

    return nil
}

func (s *PropertyFilterParams) Schema(registry huma.Registry) *huma.Schema {
    return &huma.Schema{
        Type: huma.TypeString,
    }
}

func parseAndValidateFilterItem(item string, equalityFields []string, greaterSmallerFields []string, dateFields []string) (FilterParam, error) {
    parts := strings.SplitN(item, ":", 3)

    field := parts[0]
    operator := parts[1]
    value := parts[2]

    if contains(equalityFields, field) {
        if operator != "eq" && operator != "neq" {
            return FilterParam{}, fmt.Errorf("Unsupported operator %s for field %s. Only 'eq' and 'neq' are supported.", operator, field)
        }
    } else if contains(greaterSmallerFields, field) {
        if !validation.IsValidCompareGreaterSmallerOperator(operator) {
            return FilterParam{}, fmt.Errorf("Unsupported operator %s for field %s. Supported operators: eq, neq, gt, lt, gte, lte.", operator, field)
        }
    } else if contains(dateFields, field) {
        if !validation.IsValidCompareGreaterSmallerOperator(operator) {
            return FilterParam{}, fmt.Errorf("Unsupported operator %s for field %s. Supported operators: eq, neq, gt, lt, gte, lte.", operator, field)
        }
        if !validation.IsValidDate(value) {
            return FilterParam{}, fmt.Errorf("Invalid date format: %s. Expected: YYYY-MM-DD", value)
        }
    } else {
        return FilterParam{}, fmt.Errorf("Unsupported filter field: %s", field)
    }

    return FilterParam{Field: field, Operator: operator, Value: value}, nil
}

Saya menambah PropertyFilterParams pada struct PropertyQueryParams:

type PropertyQueryParams struct {
    PaginationParams
    Filter PropertyFilterParams `query:"filters" doc:"Filter properties by various fields"`
    Sort   PropertySortParams   `query:"sorts" doc:"Sort properties by various fields"`
}

Beginilah rupa menambahkan PropertyQueryParams pada laluan (perhatikan bahawa kod Operasi itu sendiri, termasuk penerangan penapis, berada di bawah getAllPropertyOperation - Saya tidak menampal kod lengkap untuk itu, tetapi mudah-mudahan anda mendapat intipatinya) . Jika pengesahan gagal, ia akan memberikan respons 422. Saya juga menambah cara kita boleh mengulangi nilai penapis yang diluluskan:

huma.Register(api, getAllPropertyOperation(schema, "get-properties", "/properties", []string{"Properties"}),
        func(ctx context.Context, input *struct {
            models.Headers
            models.PropertyQueryParams
        }) (*models.MultiplePropertyOutput, error) {

            for _, filter := range input.Filter.Items {
                fmt.Println(filter)
            }

            return mockMultiplePropertyResponse(), err
        })
}

Saya harap ini membantu seseorang. Beritahu saya dalam ulasan, jika anda menemui penyelesaian yang lebih baik.

Atas ialah kandungan terperinci Menambah parameter pertanyaan penapis dalam Go Huma. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn