typesense-go icon indicating copy to clipboard operation
typesense-go copied to clipboard

Add Functionality to Generate Typesense Schema from Go Structs

Open doganarif opened this issue 1 year ago • 4 comments

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:

  • Reduced boilerplate code and potential for human error in schema creation.
  • Enhanced flexibility and convenience for developers working with Go and Typesense.
  • The ability to define collection names dynamically via the CollectionNamer interface.

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:

  • Unit tests for schema generation from various struct
  • Integration tests for collection creation using generated schemas.
  • Error handling tests, especially for edge cases and struct tag parsing.

PR Checklist

doganarif avatar Dec 12 '23 11:12 doganarif

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
}```

DawnKosmos avatar Mar 12 '24 20:03 DawnKosmos

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.

elee1766 avatar Apr 08 '24 04:04 elee1766

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

DawnKosmos avatar Apr 08 '24 09:04 DawnKosmos

@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.

doganarif avatar Apr 19 '24 10:04 doganarif