typesense / typesense-go

Go client for Typesense: https://github.com/typesense/typesense
Apache License 2.0
208 stars 55 forks source link

Add Functionality to Generate Typesense Schema from Go Structs #152

Open doganarif opened 9 months ago

doganarif commented 9 months ago

Change Summary

Based on the changes you've described for adding a new method CreateSchemaFromGoStruct to the go-typesense package, here's an example of how you could frame the context for your pull request: Change Summary

I've introduced a new feature in the go-typesense package that allows users to automatically generate a Typesense collection schema from a Go struct. This enhancement simplifies the process of schema creation, making it more intuitive and less error-prone, especially for users who manage data structures in Go and want to seamlessly integrate them with Typesense.

The key changes include:

A new method CreateSchemaFromGoStruct that takes a Go struct as input and generates a corresponding Typesense collection schema. This method uses reflection to parse struct fields and tags to build the schema.
Integration of CreateSchemaFromGoStruct with the existing collection creation process, allowing users to create a Typesense collection directly from a Go struct.
Support for the CollectionNamer interface, enabling custom collection naming strategies based on the struct implementation.

PR Context

This enhancement addresses the need for a more streamlined way of creating Typesense schemas directly from Go application data structures. By leveraging Go's reflection capabilities and struct tagging conventions, the CreateSchemaFromGoStruct method automates the conversion of Go structs into Typesense collection schemas.

Key benefits include:

Usage Example

type Product struct {
    ID    string `typesense:"string"`
    Name  string `typesense:"string"`
    Price float64 `typesense:"float"`
}

func main() {
    product := Product{ID: "123", Name: "Gadget", Price: 29.99}
    schema, err := typesense.Collections().CreateSchemaFromGoStruct(product)
    if err != nil {
        log.Fatal(err)
    }
    // Use schema to create a collection in Typesense
}

Tests

Comprehensive tests have been added to ensure the reliability of the new feature, including:

PR Checklist

DawnKosmos commented 6 months ago

I really like the Idea of defining the collection schema from a Go struct. At our company we often went out of sync regarding collections definitions and Go structs, also often had unnecessary errors. I implemented this behaviour with adding additional tags after the json tags. If interested I can share my code

type Patient struct {
    ID             string   `json:"id,omitempty,index"`
    PatientNumber  string   `json:"patient_number,omitempty,index"`
    Name           string   `json:"name,omitempty,index"`
    Birthdate      int64    `json:"birthdate,omitempty"`
    LastTreatment  int64    `json:"last_treatment,omitempty,index,optional"`
    OrganizationId string   `json:"organization_id,omitempty,facet"`
    LocationId     string   `json:"location_id,omitempty,facet"`
    Roles          []string `json:"roles,omitempty,index"`
}

I also created a tool to generate Typescript interface from a Golang struct.


export interface TypesensePatient {
    id : string;    // Index
    patient_number : string;    // Index
    name : string;  // Index
    birthdate : number; 
    last_treatment ?: number;   // Index
    organization_id : string;   // Facet
    location_id : string;   // Facet
    roles : string[];   // Index
}```
elee1766 commented 5 months ago

i started on this, but realized it was a non trivial task to get the full functionality i wanted, as you would need to figure out the diffs between your structs output and the existing collection to run the migration if the structs ever changed.

instead had to make a small tool with its own state that remembers which migrations have already been run, and just typing out new migrations as json.

@DawnKosmos does your code deal with schema changes? if it does, i am curious if there was an elegant solution, as i did not look too much further into it.

DawnKosmos commented 5 months ago

Do you mean syncing the Go struct with the Typesense Schema? I have not implemented it, but I see no problem in doing so.

  1. Download []api.Field From Typesense
  2. Generate []api.Field from Struct
  3. Compare them
  4. Update Schema changes
doganarif commented 4 months ago

@elee1766, I'm still encountering issues with updating schemas using this code (which I'm using in my projects). @DawnKosmos's approach is okay, but perhaps we should consider enhancing it with migrations like Goose.