typesense

package module
v0.0.0-...-da50f99 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 25, 2022 License: MIT Imports: 22 Imported by: 2

README

Typesense Generic Client GoLang [Unofficial]

This project is an implementation of the rest api proided by Typesense .

For more information see https://typesense.org/docs/ . I would like to iterate that this is the Unofficial package.

If you're looking for the offical one please see https://github.com/typesense/typesense-go

Features

  • Support For Generics out of the box .
    • no passing interface{} anys
    • no Unmarshalling on your end
  • Testability from a consumer's perspective built in the code
    • All the Clients in the code bases are interfaces
    • Mocks are also provided for all of them if you don't want to generate your own
  • Modular Implementation
    • You can extend the imlementations any way you like
  • Fluent Argument Builders
  • Migration Built out of the box .
    • Automatic migration and Manual Migration Supported.
    • Aliasing ..etc
    • Tools to help you do your own migration logic
  • Schema Attributes like index , sorting , facets ... etc supported with struct tags
  • Logging Support (thanks to the amazing http client resty ! see https://github.com/go-resty/resty)

Quick Start Guide

Quickly Creating a new instance , indexing and querying the documents

1) Installation

go get github.com/baderkha/typesense

2) Code Example With Basic Operations

  • Define a Type

    
    // UserData : a Typical model you would write for your api
    type UserData struct {
    	// your id , can be generated by you uuid , or typesense can handle it
    	ID        string `json:"id"`
    	FirstName string `json:"first_name" tsense_required:"1"`
    	// by default all fields are optional unless you specify otherwise
    	LastName string `json:"last_name" tsense_required:"true"`
    	// faceting
    	Email string `json:"email" tsense_required:"true" tsense_facet:"1"`
    	// default sorting
    	GPA float32 `json:"gpa" tsense_default_sort:"1"`
    	// default type any int is int64 , you can always override this
    	Visit     int32 `json:"visit" tsense_type:"int32"`
    	IsDeleted bool  `json:"is_deleted"  tsense_required:"true"`
    	// by default time.Time is not supported since time isn't supported in typesense
    	//this overrides this issue by turning your time data into unix epoch
    	CreatedAt types.Timestamp `json:"created_at"  tsense_required:"true"`
    	UpdatedAt types.Timestamp `json:"updated_at"  tsense_required:"true"`
    }
    
  • Init Client

    apiKey := os.Getenv("TYPESENSE_API_KEY")
    host := os.Getenv("TYPESENSE_URL")
    logging := os.Getenv("TYPESENSE_LOGGING") == "TRUE"
    // main facade client
    client := typesense.NewClient[UserData](apiKey, host, logging)
    
  • Migrate Model

    // this method will 2 resources
    // first is a collection with a version ie user_data_2022-10-10_<some-uuid>
    // second it will create an alias called user_data -> user_data_2022-10-10_<some-uuid>
    //
    // See the typesense documentation to understand the benefits of aliasing
    err := client.Migration().Auto()
    if err != nil {
    	log.Fatal(err)
    }
    
    
  • Index A Document

    // Document
    // This method will creat a record under your collection
    // your document will know exactly what collection to write it to
    err = client.Document().Index(
      &UserData{
    	ID:        "some-uuid-for-this",
    	FirstName: "Barry",
    	LastName:  "Allen",
    	Email:     "barry_allen@someFakeEmail.com",
    	GPA:       4.00,
    	Visit:     50,
    	IsDeleted: false,
    	CreatedAt: types.Timestamp(time.Now()),
    	UpdatedAt: types.Timestamp(time.Now()),
    	},
    )
    
  • Get Document

    // Document
    // this method will get the record we just created and return back
    // a *User pointer without us having to init a var and pass as reference
    // neet right ?
    doc, err := client.Document().GetById("some-uuid-for-this")
    
  • Search For Documents

    
    // english : give me everyone with the name of barry by first and last name
    // Give me that data as the first page + 20 per page max
    //
    // this is fluent so you can keep adding args and it will build the struct for you
    searchQuery := typesense.
    	NewSearchParams().
    	AddSearchTerm("barry").
    	AddQueryBy("first_name,last_name").
    	AddPage(1).
    	AddPerPage(20)
    
    // Search
    // This method will do a filter search / fuzzy search
    // res is of type typesense.SearchResult[UserData]
    res, err := client.Search().Search(searchQuery)
    

Author : Ahmad Baderkhan ❤️☀️💚

License : MIT

Documentation

Overview

Package typense : This package contains a slew of clients that implement the typesense restful interface

Each feature Section under the documentation is abstracted to its own client

IE There is a :

- Migration Client => manages collections / aliases

- Search Client => Allows advanced search

- Document Client => Allows indexing (inserting / del / update) Documents + simple gets by id export ..etc

- Cluster Client => Manages cluster / gets health and other metrics

- Main Client => A facade for all the clients the fat client that has everything if you're lazy like me

Additionally there are an interfaces for each client as well as a `mock` implementations of the interfaces if you need it in a test setting (built using testify mock package) . However , You are responsible for breaking changes in your testing setup.

Logging is also supported (it will log the outgoing http requests and http responses from typesense)

Final Note :

Create/Update/Delete Operations do not return anything except for errors if there are any . This was a concious design decision . Given that Typesense Returns correct status codes ie no need to read the json body data. If you disagree feel free to add your implementation and expand the interface

See :

https://github.com/baderkha

https://github.com/baderkha/typesen

Author : Ahmad Baderkhan

Index

Constants

View Source
const (
	// TagSort : attach this to your struct field tsense_sort
	//
	// Example :
	//           // your model
	//			 type Model struct {
	//				Field string `tsense_sort:"1"` // this will tell typesense you want this field sorted
	//			 }
	//
	TagSort = "tsense_sort"
	// TagIndex : attach this to your struct field tsense_index
	//
	// Example :
	//           // your model
	//			 type Model struct {
	//				Field string `tsense_index:"1"` // this will tell typesense you want this field indexed
	//			 }
	//
	TagIndex = "tsense_index"
	// TagRequired : attach this to your struct field tsense_required
	//
	// Example :
	//           // your model
	//			 type Model struct {
	//				Field string `tsense_required:"1"` // this will tell typesense you want this field to be required during creates
	//			 }
	//
	TagRequired = "tsense_required"
	// TagRequired : attach this to your struct field tsense_facet
	//
	// Example :
	//           // your model
	//			 type Model struct {
	//				Field string `tsense_facet:"1"` // this will tell typesense you want this field as a facet
	//			 }
	//
	TagFacet = "tsense_facet"
	// TagTypeOverride : attach this to your struct field tsense_type
	//
	// Example :
	//           // your model
	//			type Model struct {
	//				Field int8 `tsense_type:"int32"` // this will tell typesense you want
	//												 // this field to override the type instead of the auto type (int64)
	//			}
	//
	TagTypeOverride = "tsense_type"
	// TagTypeOverride : attach this to your struct field tsense_default_sort
	//
	// Example :
	//           // your model
	//			type Model struct {
	//				Field string `tsense_default_sort:"1"` // this will tell typesense you want
	//												   // this field to be the default sort field
	//			}
	//
	TagDefaultSort = "tsense_default_sort"
)
View Source
const (
	// DocumentActionUpsert : upsert a bunch of documents . if update (document must have all full required fields)
	DocumentActionUpsert = "upsert"
	// DocumentActionUpsert : update a bunch of documents , error if id does not exist
	DocumentActionUpdate = "update"
	// DocumentActionUpsert : create a new document / documents , error if already exists it will merge
	DocumentActionEmplace = "emplace"

	// DocumentDirtyStratCORreject : Attempt coercion of the field's value to previously inferred type.
	// If coercion fails, reject the write outright with an error message.
	DocumentDirtyStratCORreject = "corece_or_reject"
	// DocumentDirtyStratReject : Reject the document outright.
	DocumentDirtyStratReject = "reject"
	// DocumentDirtyStratDrop : Drop the particular field and index the rest of the document.
	DocumentDirtyStratDrop = "drop"
	// DocumentDirtyStratCODrop :Attempt coercion of the field's value to previously inferred type.
	// If coercion fails, drop the particular field and index the rest of the document.
	DocumentDirtyStratCODrop = "corece_or_drop"
)

Variables

This section is empty.

Functions

func OverrideDocBatchSize

func OverrideDocBatchSize(docBSize int64)

OverrideDocBatchSize : override the batch size when doing document operations

func OverrideDocDirtyStrat

func OverrideDocDirtyStrat(dirtyStrat string)

OverrideDocDirtyStrat : Override the dirty value strategy when uploading documents

func OverrideFS

func OverrideFS(newFs afero.Fs)

OverrideFS : change the file ssytem that will be used in the client

call this before constructing the Client . if you want a different file system

see :

https://github.com/spf13/afero#available-backends

// forexample you can have a s3 bucket to store your jsonl files

https://github.com/fclairamb/afero-s3 // (cool right :))

func SetHTTPRetryCount

func SetHTTPRetryCount(retryCount int)

SetHTTPRetryCount : sets the retry count for the requests

func SetSearchCache

func SetSearchCache(isSearchCache bool)

SetSearchCache : sets search cache when using the search client

func SetSearchCacheTTL

func SetSearchCacheTTL(searchCacheTTL int)

SetSearchCache : sets search cache when using the search client

Types

type Alias

type Alias struct {
	Name           string `json:"name "`
	CollectionName string `json:"collection_name"`
}

Alias : alias to a collection

type Client

type Client[T any] struct {
	// contains filtered or unexported fields
}

Client : General Client that contains all operations supported by typesense

func (Client[T]) Cluster

func (c Client[T]) Cluster() IClusterClient

Cluster : return back cluster client

func (Client[T]) Document

func (c Client[T]) Document() IDocumentClient[T]

Document : returns back Document client

func (Client[T]) Migration

func (c Client[T]) Migration() IMigration[T]

Migration : returns back migration client

func (Client[T]) Search

func (c Client[T]) Search() ISearchClient[T]

Search : returns back Search client

type ClusterClient

type ClusterClient struct {
	// contains filtered or unexported fields
}

func (*ClusterClient) CreateSnapShot

func (c *ClusterClient) CreateSnapShot(path string) error

CreateSnapShot : createa a snapshot for the client

func (ClusterClient) GetAlias

func (m ClusterClient) GetAlias(aliasName string) (doesExist bool, alias Alias)

GetAlias : gets an alias label and returns back collection name

func (ClusterClient) GetAliasCached

func (m ClusterClient) GetAliasCached(aliasName string) (doesExist bool, alias Alias)

GetAlias : gets an alias label and returns back collection name

func (ClusterClient) GetCollection

func (m ClusterClient) GetCollection(collection string) (doesExist bool, col Collection)

GetCollection : gets a collection and checks if it exists

func (ClusterClient) GetCollectionFromAlias

func (m ClusterClient) GetCollectionFromAlias(aliasName string) (doesExist bool, col Collection)

GetCollectionFromAlias : get underlying collection for an alias name if the binding exists

func (*ClusterClient) Health

func (c *ClusterClient) Health() bool

Health : pings the cluster for health information

func (ClusterClient) JSONLToByteSlice

func (m ClusterClient) JSONLToByteSlice(jsonL io.Reader) ([]byte, error)

func (*ClusterClient) Metrics

func (c *ClusterClient) Metrics() (map[string]interface{}, error)

Metrics : general metrics about the cluster

func (ClusterClient) ModelToJSONLines

func (m ClusterClient) ModelToJSONLines(mod []*T) []byte

func (*ClusterClient) ReelectLeader

func (c *ClusterClient) ReelectLeader() (bool, error)

ReelectLeader : triggers follower note to init rafting process

func (ClusterClient) Req

func (m ClusterClient) Req() *resty.Request

func (*ClusterClient) Stats

func (c *ClusterClient) Stats() (map[string]interface{}, error)

Stats : shows latency stats

func (*ClusterClient) ToggleSlowRequest

func (c *ClusterClient) ToggleSlowRequest(time int64) (bool, error)

ToggleSlowRequest : enable logging of requests that take too long

func (ClusterClient) VersionCollectionName

func (m ClusterClient) VersionCollectionName(colName string) string

VersionCollectionName : adds a version to the collectioName

type ClusterOperationResponse

type ClusterOperationResponse struct {
	Success bool `json:"success"`
}

type Collection

type Collection struct {
	Name                string            `json:"name"`
	Fields              []CollectionField `json:"fields"`
	DefaultSortingField string            `json:"default_sorting_field"`
}

Collection : typesense collection

type CollectionField

type CollectionField struct {
	Facet    bool `json:"facet"`
	Index    bool `json:"index"`
	Optional bool `json:"optional"`
	Sort     bool `json:"sort"`

	Name string `json:"name"`
	Type string `json:"type"`
}

CollectionField : field for a typesense collection

type CollectionFieldUpdate

type CollectionFieldUpdate struct {
	Facet    bool   `json:"facet"`
	Index    bool   `json:"index"`
	Optional bool   `json:"optional"`
	Sort     bool   `json:"sort"`
	Drop     bool   `json:"drop"`
	Name     string `json:"name"`
	Type     string `json:"type"`
}

CollectionField : field for a typesense collection

type CollectionUpdate

type CollectionUpdate struct {
	Fields              []CollectionField `json:"fields"`
	DefaultSortingField string            `json:"default_sorting_field"`
}

Collection : typesense collection

type DocumentClient

type DocumentClient[T any] struct {
	// contains filtered or unexported fields
}

DocumentClient : Document client (meant for simple gets , post , patch , deletes

func (*DocumentClient[T]) DeleteById

func (d *DocumentClient[T]) DeleteById(id string) error

func (*DocumentClient[T]) DeleteManyWithQuery

func (d *DocumentClient[T]) DeleteManyWithQuery(query string) error

func (*DocumentClient[T]) ExportAll

func (d *DocumentClient[T]) ExportAll() ([]byte, error)

func (*DocumentClient[T]) ExportAllWithQuery

func (d *DocumentClient[T]) ExportAllWithQuery(query string) ([]byte, error)

func (DocumentClient) GetAlias

func (m DocumentClient) GetAlias(aliasName string) (doesExist bool, alias Alias)

GetAlias : gets an alias label and returns back collection name

func (DocumentClient) GetAliasCached

func (m DocumentClient) GetAliasCached(aliasName string) (doesExist bool, alias Alias)

GetAlias : gets an alias label and returns back collection name

func (*DocumentClient[T]) GetById

func (d *DocumentClient[T]) GetById(id string) (*T, error)

func (DocumentClient) GetCollection

func (m DocumentClient) GetCollection(collection string) (doesExist bool, col Collection)

GetCollection : gets a collection and checks if it exists

func (DocumentClient) GetCollectionFromAlias

func (m DocumentClient) GetCollectionFromAlias(aliasName string) (doesExist bool, col Collection)

GetCollectionFromAlias : get underlying collection for an alias name if the binding exists

func (*DocumentClient[T]) ImportMany

func (d *DocumentClient[T]) ImportMany(jsonLines []byte, action string) error

func (*DocumentClient[T]) ImportManyFromFile

func (d *DocumentClient[T]) ImportManyFromFile(path string, action string) error

func (*DocumentClient[T]) Index

func (d *DocumentClient[T]) Index(m *T) error

func (*DocumentClient[T]) IndexMany

func (d *DocumentClient[T]) IndexMany(m []*T, action string) error

func (*DocumentClient[T]) IsExistById

func (d *DocumentClient[T]) IsExistById(id string) bool

IsExistById : check if document exists

func (DocumentClient) JSONLToByteSlice

func (m DocumentClient) JSONLToByteSlice(jsonL io.Reader) ([]byte, error)

func (DocumentClient) ModelToJSONLines

func (m DocumentClient) ModelToJSONLines(mod []*T) []byte

func (DocumentClient) Req

func (m DocumentClient) Req() *resty.Request

func (*DocumentClient[T]) Update

func (d *DocumentClient[T]) Update(m *T, id string) error

func (DocumentClient) VersionCollectionName

func (m DocumentClient) VersionCollectionName(colName string) string

VersionCollectionName : adds a version to the collectioName

func (*DocumentClient[T]) WithBatchSize

func (d *DocumentClient[T]) WithBatchSize(batchSize int64) IDocumentClient[T]

func (*DocumentClient[T]) WithCollectionName

func (d *DocumentClient[T]) WithCollectionName(colName string) IDocumentClient[T]

func (*DocumentClient[T]) WithDirtyStrat

func (d *DocumentClient[T]) WithDirtyStrat(dirtyStrat string) IDocumentClient[T]

func (*DocumentClient[T]) WithoutAutoAlias

func (d *DocumentClient[T]) WithoutAutoAlias() IDocumentClient[T]

type GroupedHits

type GroupedHits[T any] struct {
	GroupKey []string `json:"group_key"`
	Hits     []Hit[T] `json:"hits"`
}

GroupedHits : results , houses your documents and group by info

type Highlights

type Highlights struct {
	Field         string   `json:"field"`
	MatchedTokens []string `json:"matched_tokens"`
	Snippet       string   `json:"snippet"`
}

Highlights : more metadata

type Hit

type Hit[T any] struct {
	Document   T          `json:"document"`
	Highlights Highlights `json:"highlights"`
	TextMatch  int        `json:"text_match"`
}

Hits : results , houses your documents

type IClient

type IClient[T any] interface {
	// Migration : returns back migration client
	Migration() IMigration[T]
	// Document : returns back Document client
	Document() IDocumentClient[T]
	// Search : returns back Search client
	Search() ISearchClient[T]
	// Cluster : return back cluster client
	Cluster() IClusterClient
}

IClient : General Client that contains all operations supported by typesense

func NewClient

func NewClient[T any](apiKey string, host string, logging bool) IClient[T]

NewClient : default client , has all the other clients wrapped

func NewClientNoGeneric

func NewClientNoGeneric(apiKey string, host string, logging bool) IClient[any]

NewClientNoGeneric : default client , has all the other clients wrapped . This will not have any generic bindings

usage is limited

type IClusterClient

type IClusterClient interface {
	// Health : pings the cluster for health information
	Health() bool
	// Stats : shows latency stats
	Stats() (map[string]interface{}, error)
	// Metrics : general metrics about the cluster
	Metrics() (map[string]interface{}, error)
	// ReelectLeader : triggers follower note to init rafting process
	ReelectLeader() (bool, error)
	// ToggleSlowRequest : enable logging of requests that take too long
	ToggleSlowRequest(reqTimeMS int64) (bool, error)
	// CreateSnapShot : createa a snapshot for the client
	CreateSnapShot(path string) error
}

IClusterClient : cluster client

func NewClusterClient

func NewClusterClient(apiKey string, host string, logging bool) IClusterClient

NewClusterClient : client for cluster operations

type IDocumentClient

type IDocumentClient[T any] interface {
	// GetById : get 1 document by id otherwise error out not found
	GetById(id string) (m *T, err error)
	// IsExistById : check if document exists
	IsExistById(id string) bool
	// ExportAll : Export all the document as a byte slice (string represntation of jsonL)
	ExportAll() ([]byte, error) // exports as []byte (string represenation of )
	// ExportAll : Export all the document with a query filter as a byte slice (string represntation of jsonL)
	ExportAllWithQuery(query string) ([]byte, error)
	// Index : create / add new document . can also do upserts
	Index(m *T) error
	// Update : update existing document completley. will error out if required details are missing or if document not found
	Update(m *T, id string) error
	// DeleteById : Delete by an id
	DeleteById(id string) error
	// DeleteManyWithQuery : delete more than 1 with a query criteria
	DeleteManyWithQuery(query string) error
	// IndexMany : create multiple documents (transforms them to jsonL behind the scenes)
	IndexMany(m []*T, action string) error
	// ImportMany : import many documents with json lines
	ImportMany(jsonLines []byte, action string) error
	// ImportManyFromFile : opens a file from path and sends it to your typesense backend
	//
	// This gives you the operatunity to specifc the file system to be used
	// By default this package uses the os file system , but since this client is built
	// with the afero package (see https://github.com/spf13/afero) your file system options are limitless
	//
	// Example :
	//				// your model
	// 				type User struct {
	//					FirstName string `json:"first_name" tsense_sort:"1" tsense_required:"1"`
	//				}
	//				func main() {
	//					filePath := "/tmp/some_file.jsonl"
	//					memoryFS := afero.NewMemMapFs()
	//
	//					// memory file system instead of the os
	//					// (there's a bunch of implementations you can check out)
	//					typesense.OverrideFS(memoryFS)
	//
	//					docClient := typesense.NewDocumentClient[User]("api key" , "host" , false)
	//					err := docClient.ImportManyFromFile(
	//							filePath,
	//							typesense.DocumentActionUpsert,
	//						)
	//					if err != nil {
	//						log.Fatal(err)
	//					}
	//				}
	//
	ImportManyFromFile(path string, action string) error
	// WithBatchSize : Override The batch Size for a local operation and not globally
	WithBatchSize(batchSize int64) IDocumentClient[T]
	// WithDirtyStrat : Override the dirty document strategy for a local operation and not globally
	WithDirtyStrat(dirtyStrat string) IDocumentClient[T]
	// WithCollectionName : Override the collection name for local operations and not globally
	WithCollectionName(colName string) IDocumentClient[T]
	// WithoutAutoAlias : if you used the migration tool , it probably auto aliased your collection . if you're doing your own migration
	//                       then call this method to not call the alias route to resolve the doc
	WithoutAutoAlias() IDocumentClient[T]
}

DocumentClient : Document client (meant for simple gets , post , patch , deletes

func NewDocumentClient

func NewDocumentClient[T any](apiKey string, host string, logging bool) IDocumentClient[T]

NewDocumentClient : create a new document client which allows you to do basic crud operations on documents

type IMigration

type IMigration[T any] interface {
	// AliasCollection : create an alias for a collection
	AliasCollection(a *Alias) error
	// Auto : AutoMigrate Depending on the model it will construct a collection via typesense , alias it and maintain the schema
	// Example:
	//			// Your Model you want to map to the client
	//			type MyCoolModel struct {
	//				Field string `db:"field"`
	//			}
	//
	//			func main (){
	//				migration := typesense.NewModelMigration[MyCoolModel]("<api_key>","<http_server_url>",false)
	//				// your alias will be my_cool_model -> my_cool_model_2022-10-10_<SomeHash>
	//				// where the latter value is the underlying collection name
	//				migration.Auto()
	//			}
	//
	Auto() error
	// DeleteAliasCollection : deletes an alias pointer
	DeleteAliasCollection(aliasName string) error
	// DeleteCollection : deletes collection and collection data
	DeleteCollection(colName string, col *CollectionUpdate) error
	// GetAlias : gets an alias label and returns back collection name
	GetAlias(aliasName string) (doesExist bool, alias Alias)
	// GetCollection : gets a collection and checks if it exists
	GetCollection(collection string) (doesExist bool, col Collection)
	// GetCollectionFromAlias : get underlying collection for an alias name if the binding exists
	GetCollectionFromAlias(aliasName string) (doesExist bool, col Collection)
	// Manual : if you don't trust auto migration , you can always migrate it yourself
	// or build your own auto schema converter yourself .
	//
	// Note that the implementation uses aliasing .
	//
	// Example:
	//			// Your Model you want to map to the client
	//			type MyCoolModel struct {
	//				Field string `db:"field"`
	//			}
	//
	//			func main (){
	//				migration := typesense.NewModelMigration[MyCoolModel]("<api_key>","<http_server_url>",false)
	//
	//				// your alias will be my_cool_model -> my_cool_model_2022-10-10_<SomeHash>
	//				// where the latter value is the underlying collection name
	//				migration.Manual(&typesense.Collection{Name : "my_cool_model"},true)
	//				// no alias created your collectio nname is my_cool_model
	//				migration.Manual(&typesense.Collection{Name : "my_cool_model"},false)
	//			}
	//
	Manual(col *Collection, alias bool) error
	// ModelToCollection : converts a model to a typesense collection , useful for manual migration
	ModelToCollection() (*Collection, error)
	// MustAuto : Must auto migrate basically calls AutoMigrate and panics on failure
	MustAuto()
	// MustAuto : Must auto migrate basically calls AutoMigrate and panics on failure
	MustManual(col *Collection, alias bool)
	// NewCollection : create a new collection
	NewCollection(col *Collection) error
	// UpdateCollection : updates collection schema
	UpdateCollection(colName string, col *CollectionUpdate) error
	// VersionCollectionName : adds a version to the collectioName
	VersionCollectionName(colName string) string
}

Migration : Migration Client for typesense

Houses Both Collection / Alias Operations + Adds a handy AutoMigration function / ManualMigration

func NewManualMigration

func NewManualMigration(apiKey string, host string, logging bool) IMigration[any]

NewManualMigration : Migration if you want to do your own thing and use the low level wrapper methods for the rest calls

Disclaimer :

// Do not use Auto Method
migrator := typesense.NewManualMigration("","","")
migrator.Auto() // should panic or error or give you a bad status code

// instead you will have to make the calls yourself

func NewModelMigration

func NewModelMigration[T any](apiKey string, host string, logging bool) IMigration[T]

NewModelMigration : Migration if you want to use Model Dependent migration ie tie your migration client to a A Specific struct declaration

type ISearchClient

type ISearchClient[T any] interface {
	// Search : search without grouping and allows for pagination
	Search(s *SearchParameters) (SearchResult[T], error)
	// SearchGrouped : search with grouping by field and allows for pagniantion
	SearchGrouped(s *SearchGroupedParameters) (SearchResultGrouped[T], error)
	// WithCollectionName : Override the collection name for local operations and not globally
	WithCollectionName(colName string) ISearchClient[T]
	// WithoutDocAutoAlias : if you used the migration tool , it probably auto aliased your collection . if you're doing your own migration
	//                       then call this method to not call the alias route to resolve the doc
	WithoutAutoAlias() ISearchClient[T]
}

ISearchClient : search client interface

func NewSearchClient

func NewSearchClient[T any](apiKey string, host string, logging bool) ISearchClient[T]

NewSearchClient : create a new search client which allows you to do advanced search

type Migration

type Migration[T any] struct {
	// contains filtered or unexported fields
}

Migration : Migration Client for typesense

Houses Both Collection / Alias Operations + Adds a handy AutoMigration function / ManualMigration

func (Migration[T]) AliasCollection

func (m Migration[T]) AliasCollection(a *Alias) error

AliasCollection : create an alias for a collection

func (Migration[T]) Auto

func (m Migration[T]) Auto() error

Auto : AutoMigrate Depending on the model it will construct a collection via typesense , alias it and maintain the schema Example:

// Your Model you want to map to the client
type MyCoolModel struct {
	Field string `db:"field"`
}

func main (){
	migration := typesense.NewModelMigration[MyCoolModel]("<api_key>","<http_server_url>",false)
	// your alias will be my_cool_model -> my_cool_model_2022-10-10_<SomeHash>
	// where the latter value is the underlying collection name
	migration.Auto()
}

func (Migration[T]) DeleteAliasCollection

func (m Migration[T]) DeleteAliasCollection(aliasName string) error

DeleteAliasCollection : deletes an alias pointer

func (Migration[T]) DeleteCollection

func (m Migration[T]) DeleteCollection(colName string, col *CollectionUpdate) error

DeleteCollection : deletes collection and collection data

func (Migration) GetAlias

func (m Migration) GetAlias(aliasName string) (doesExist bool, alias Alias)

GetAlias : gets an alias label and returns back collection name

func (Migration) GetAliasCached

func (m Migration) GetAliasCached(aliasName string) (doesExist bool, alias Alias)

GetAlias : gets an alias label and returns back collection name

func (Migration) GetCollection

func (m Migration) GetCollection(collection string) (doesExist bool, col Collection)

GetCollection : gets a collection and checks if it exists

func (Migration) GetCollectionFromAlias

func (m Migration) GetCollectionFromAlias(aliasName string) (doesExist bool, col Collection)

GetCollectionFromAlias : get underlying collection for an alias name if the binding exists

func (Migration) JSONLToByteSlice

func (m Migration) JSONLToByteSlice(jsonL io.Reader) ([]byte, error)

func (Migration[T]) Manual

func (m Migration[T]) Manual(col *Collection, alias bool) error

Manual : if you don't trust auto migration , you can always migrate it yourself or build your own auto schema converter yourself .

Note that the implementation uses aliasing .

Example:

// Your Model you want to map to the client
type MyCoolModel struct {
	Field string `db:"field"`
}

func main (){
	migration := typesense.NewModelMigration[MyCoolModel]("<api_key>","<http_server_url>",false)

	// your alias will be my_cool_model -> my_cool_model_2022-10-10_<SomeHash>
	// where the latter value is the underlying collection name
	migration.Manual(&typesense.Collection{Name : "my_cool_model"},true)
	// no alias created your collectio nname is my_cool_model
	migration.Manual(&typesense.Collection{Name : "my_cool_model"},false)
}

func (Migration[T]) ModelToCollection

func (m Migration[T]) ModelToCollection() (*Collection, error)

ModelToCollection : converts a model to a typesense collection , useful for manual migration

func (Migration) ModelToJSONLines

func (m Migration) ModelToJSONLines(mod []*T) []byte

func (Migration[T]) MustAuto

func (m Migration[T]) MustAuto()

MustAuto : Must auto migrate basically calls AutoMigrate and panics on failure

func (Migration[T]) MustManual

func (m Migration[T]) MustManual(col *Collection, alias bool)

MustManual : Must manually migrate calls Manual and panics on failure

func (Migration[T]) NewCollection

func (m Migration[T]) NewCollection(col *Collection) error

NewCollection : create a new collection

func (Migration) Req

func (m Migration) Req() *resty.Request

func (Migration[T]) UpdateCollection

func (m Migration[T]) UpdateCollection(colName string, col *CollectionUpdate) error

UpdateCollection : updates collection schema

func (Migration) VersionCollectionName

func (m Migration) VersionCollectionName(colName string) string

VersionCollectionName : adds a version to the collectioName

type RequestParams

type RequestParams struct {
	CollectionName string `json:"collection_name"`
	PerPage        int    `json:"per_page"`
	Q              string `json:"q"`
}

RequestParams : metadata describing the request params you used

type SearchClient

type SearchClient[T any] struct {
	// contains filtered or unexported fields
}

SearchClient : a client that allows you to do advanced queries for a specified model

func (SearchClient) GetAlias

func (m SearchClient) GetAlias(aliasName string) (doesExist bool, alias Alias)

GetAlias : gets an alias label and returns back collection name

func (SearchClient) GetAliasCached

func (m SearchClient) GetAliasCached(aliasName string) (doesExist bool, alias Alias)

GetAlias : gets an alias label and returns back collection name

func (SearchClient) GetCollection

func (m SearchClient) GetCollection(collection string) (doesExist bool, col Collection)

GetCollection : gets a collection and checks if it exists

func (SearchClient) GetCollectionFromAlias

func (m SearchClient) GetCollectionFromAlias(aliasName string) (doesExist bool, col Collection)

GetCollectionFromAlias : get underlying collection for an alias name if the binding exists

func (SearchClient) JSONLToByteSlice

func (m SearchClient) JSONLToByteSlice(jsonL io.Reader) ([]byte, error)

func (SearchClient) ModelToJSONLines

func (m SearchClient) ModelToJSONLines(mod []*T) []byte

func (SearchClient) Req

func (m SearchClient) Req() *resty.Request

func (*SearchClient[T]) Search

func (s *SearchClient[T]) Search(search *SearchParameters) (SearchResult[T], error)

Search : search without grouping and allows for pagination

func (*SearchClient[T]) SearchGrouped

func (s *SearchClient[T]) SearchGrouped(search *SearchGroupedParameters) (SearchResultGrouped[T], error)

SearchGrouped : search with grouping by field and allows for pagniantion

func (SearchClient) VersionCollectionName

func (m SearchClient) VersionCollectionName(colName string) string

VersionCollectionName : adds a version to the collectioName

func (*SearchClient[T]) WithCollectionName

func (s *SearchClient[T]) WithCollectionName(colName string) ISearchClient[T]

WithCollectionName : Override the collection name for local operations and not globally

func (*SearchClient[T]) WithoutAutoAlias

func (s *SearchClient[T]) WithoutAutoAlias() ISearchClient[T]

WithoutDocAutoAlias : if you used the migration tool , it probably auto aliased your collection . if you're doing your own migration

then call this method to not call the alias route to resolve the doc

type SearchGroupedParameters

type SearchGroupedParameters struct {
	SearchParameters
	GroupBy    string `json:"group_by,omitempty"`
	GroupLimit string `json:"group_limit,omitempty"`
}

SearchGroupedParameters : Search Parametes with grouping added

func NewSearchGroupedParams

func NewSearchGroupedParams() *SearchGroupedParameters

func (*SearchGroupedParameters) AddGroupBy

func (s *SearchGroupedParameters) AddGroupBy(GroupBy string) *SearchGroupedParameters

func (*SearchGroupedParameters) AddGroupLimit

func (s *SearchGroupedParameters) AddGroupLimit(GroupLimit int) *SearchGroupedParameters

type SearchParameters

type SearchParameters struct {
	SearchTerm string `json:"q,omitempty"`
	QueryBy    string `json:"query_by,omitempty"`
	FilterBy   string `json:"filter_by,omitempty"`
	SortBy     string `json:"sort_by,omitempty"`
	Page       string `json:"page,omitempty"`
	PerPage    string `json:"per_page,omitempty"`
}

SearchParameters : Search parameters for the serarcvh client

func NewSearchParams

func NewSearchParams() *SearchParameters

func (*SearchParameters) AddFilterBy

func (s *SearchParameters) AddFilterBy(fieldFilterBy string) *SearchParameters

func (*SearchParameters) AddPage

func (s *SearchParameters) AddPage(page int) *SearchParameters

func (*SearchParameters) AddPerPage

func (s *SearchParameters) AddPerPage(perPage int) *SearchParameters

func (*SearchParameters) AddQueryBy

func (s *SearchParameters) AddQueryBy(fieldQueryBy string) *SearchParameters

func (*SearchParameters) AddSearchTerm

func (s *SearchParameters) AddSearchTerm(q string) *SearchParameters

func (*SearchParameters) AddSortBy

func (s *SearchParameters) AddSortBy(SortBy string) *SearchParameters

type SearchResult

type SearchResult[T any] struct {
	SearchResultBase
	Hits []Hit[T] `json:"hits"`
}

SearchResult : search result without grouping

func (*SearchResult[T]) GetDocuments

func (s *SearchResult[T]) GetDocuments() []*T

GetDocuments : returns the documents

type SearchResultBase

type SearchResultBase struct {
	FacetCounts   []string      `json:"facet_counts"`
	Found         int           `json:"found"`
	OutOf         int           `json:"out_of"`
	Page          int           `json:"page"`
	RequestParams RequestParams `json:"request_params"`
	SearchTimeMs  int           `json:"search_time_ms"`
}

type SearchResultGrouped

type SearchResultGrouped[T any] struct {
	SearchResultBase
	GroupedHits []GroupedHits[T] `json:"grouped_hits"`
}

SearchResultGrouped : search result with grouping

func (*SearchResultGrouped[T]) GetDocuments

func (s *SearchResultGrouped[T]) GetDocuments() map[string][]*T

GetDocuments : returns the documents via group example :

{"first_name,last_name" : [{first_name : "something" , "last_name" : "something_else"}]}

Directories

Path Synopsis
cmd
pkg

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL