Skip to content

Commit

Permalink
feat: add localized atteribute for search and index settings
Browse files Browse the repository at this point in the history
  • Loading branch information
Ja7ad committed Oct 2, 2024
1 parent 2a54493 commit 1f4a74c
Show file tree
Hide file tree
Showing 9 changed files with 975 additions and 468 deletions.
10 changes: 10 additions & 0 deletions .code-samples.meilisearch.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -935,3 +935,13 @@ update_proximity_precision_settings_1: |-
client.Index("books").UpdateProximityPrecision(ByAttribute)
reset_proximity_precision_settings_1: |-
client.Index("books").ResetProximityPrecision()
search_parameter_reference_locales_1: |-
client.index('INDEX_NAME').search('進撃の巨人', { locales: ['jpn'] })
get_localized_attribute_settings_1: |-
client.index('INDEX_NAME').GetLocalizedAttributes()
update_localized_attribute_settings_1: |-
client.index('INDEX_NAME').UpdateLocalizedAttributes([
{ attributePatterns: ['jpn'], locales: ['*_ja'] },
])
reset_localized_attribute_settings_1: |-
client.index('INDEX_NAME').ResetLocalizedAttributes()
22 changes: 22 additions & 0 deletions index.go
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,28 @@ type IndexManager interface {
// https://www.meilisearch.com/docs/reference/api/settings#reset-proximity-precision-settings
ResetProximityPrecisionWithContext(ctx context.Context) (*TaskInfo, error)

// GetLocalizedAttributes get the localized attributes settings of an index
// https://www.meilisearch.com/docs/reference/api/settings#get-localized-attributes-settings
GetLocalizedAttributes() ([]*LocalizedAttributes, error)

// GetLocalizedAttributesWithContext get the localized attributes settings of an index using the provided context for cancellation
// https://www.meilisearch.com/docs/reference/api/settings#get-localized-attributes-settings
GetLocalizedAttributesWithContext(ctx context.Context) ([]*LocalizedAttributes, error)

// UpdateLocalizedAttributes update the localized attributes settings of an index
// https://www.meilisearch.com/docs/reference/api/settings#update-localized-attribute-settings
UpdateLocalizedAttributes(request []*LocalizedAttributes) (*TaskInfo, error)

// UpdateLocalizedAttributesWithContext update the localized attributes settings of an index using the provided context for cancellation
// https://www.meilisearch.com/docs/reference/api/settings#update-localized-attribute-settings
UpdateLocalizedAttributesWithContext(ctx context.Context, request []*LocalizedAttributes) (*TaskInfo, error)

// ResetLocalizedAttributes reset the localized attributes settings
ResetLocalizedAttributes() (*TaskInfo, error)

// ResetLocalizedAttributesWithContext reset the localized attributes settings using the provided context for cancellation
ResetLocalizedAttributesWithContext(ctx context.Context) (*TaskInfo, error)

// WaitForTask waits for a task to complete by its UID with the given interval.
WaitForTask(taskUID int64, interval time.Duration) (*Task, error)

Expand Down
26 changes: 24 additions & 2 deletions index_search_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ func TestIndex_Search(t *testing.T) {
"book_id": float64(123), "title": "Pride and Prejudice",
},
},
EstimatedTotalHits: 21,
EstimatedTotalHits: 22,
Offset: 0,
Limit: 1,
},
Expand Down Expand Up @@ -735,6 +735,28 @@ func TestIndex_Search(t *testing.T) {
want: nil,
wantErr: true,
},
{
name: "TestIndexSearchWithLocate",
args: args{
UID: "indexUID",
client: sv,
query: "王子",
request: &SearchRequest{
Locate: []Locate{JPN},
},
},
want: &SearchResponse{
Hits: []interface{}{
map[string]interface{}{
"book_id": float64(1050), "title": "星の王子さま",
},
},
EstimatedTotalHits: 1,
Offset: 0,
Limit: 20,
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down Expand Up @@ -1463,7 +1485,7 @@ func TestIndex_SearchWithSort(t *testing.T) {
"book_id": float64(7), "title": "Don Quixote",
},
},
EstimatedTotalHits: 21,
EstimatedTotalHits: 22,
Offset: 0,
Limit: 4,
},
Expand Down
62 changes: 62 additions & 0 deletions index_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -1102,3 +1102,65 @@ func (i *index) ResetProximityPrecisionWithContext(ctx context.Context) (*TaskIn
}
return resp, nil
}

func (i *index) GetLocalizedAttributes() ([]*LocalizedAttributes, error) {
return i.GetLocalizedAttributesWithContext(context.Background())
}

func (i *index) GetLocalizedAttributesWithContext(ctx context.Context) ([]*LocalizedAttributes, error) {
resp := make([]*LocalizedAttributes, 0)
req := &internalRequest{
endpoint: "/indexes/" + i.uid + "/settings/localized-attributes",
method: http.MethodGet,
withRequest: nil,
withResponse: &resp,
acceptedStatusCodes: []int{http.StatusOK},
functionName: "GetLocalizedAttributes",
}
if err := i.client.executeRequest(ctx, req); err != nil {
return nil, err
}
return resp, nil
}

func (i *index) UpdateLocalizedAttributes(request []*LocalizedAttributes) (*TaskInfo, error) {
return i.UpdateLocalizedAttributesWithContext(context.Background(), request)
}

func (i *index) UpdateLocalizedAttributesWithContext(ctx context.Context, request []*LocalizedAttributes) (*TaskInfo, error) {

resp := new(TaskInfo)
req := &internalRequest{
endpoint: "/indexes/" + i.uid + "/settings/localized-attributes",
method: http.MethodPut,
withRequest: request,
withResponse: resp,
contentType: contentTypeJSON,
acceptedStatusCodes: []int{http.StatusAccepted},
functionName: "UpdateLocalizedAttributes",
}
if err := i.client.executeRequest(ctx, req); err != nil {
return nil, err
}
return resp, nil
}

func (i *index) ResetLocalizedAttributes() (*TaskInfo, error) {
return i.ResetLocalizedAttributesWithContext(context.Background())
}

func (i *index) ResetLocalizedAttributesWithContext(ctx context.Context) (*TaskInfo, error) {
resp := new(TaskInfo)
req := &internalRequest{
endpoint: "/indexes/" + i.uid + "/settings/localized-attributes",
method: http.MethodDelete,
withRequest: nil,
withResponse: resp,
acceptedStatusCodes: []int{http.StatusAccepted},
functionName: "ResetLocalizedAttributes",
}
if err := i.client.executeRequest(ctx, req); err != nil {
return nil, err
}
return resp, nil
}
69 changes: 69 additions & 0 deletions index_settings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ func TestIndex_GetSettings(t *testing.T) {
SeparatorTokens: make([]string, 0),
NonSeparatorTokens: make([]string, 0),
Dictionary: make([]string, 0),
LocalizedAttributes: nil,
},
},
{
Expand All @@ -284,6 +285,7 @@ func TestIndex_GetSettings(t *testing.T) {
SeparatorTokens: make([]string, 0),
NonSeparatorTokens: make([]string, 0),
Dictionary: make([]string, 0),
LocalizedAttributes: nil,
},
},
}
Expand Down Expand Up @@ -893,6 +895,7 @@ func TestIndex_ResetSettings(t *testing.T) {
SeparatorTokens: make([]string, 0),
NonSeparatorTokens: make([]string, 0),
Dictionary: make([]string, 0),
LocalizedAttributes: nil,
},
},
{
Expand Down Expand Up @@ -920,6 +923,7 @@ func TestIndex_ResetSettings(t *testing.T) {
SeparatorTokens: make([]string, 0),
NonSeparatorTokens: make([]string, 0),
Dictionary: make([]string, 0),
LocalizedAttributes: nil,
},
},
}
Expand Down Expand Up @@ -1698,6 +1702,12 @@ func TestIndex_UpdateSettings(t *testing.T) {
SeparatorTokens: make([]string, 0),
NonSeparatorTokens: make([]string, 0),
Dictionary: make([]string, 0),
LocalizedAttributes: []*LocalizedAttributes{
{
Locales: []Locate{JPN, ENG},
AttributePatterns: []string{"*_ja"},
},
},
},
},
wantTask: &TaskInfo{
Expand All @@ -1720,6 +1730,12 @@ func TestIndex_UpdateSettings(t *testing.T) {
SeparatorTokens: make([]string, 0),
NonSeparatorTokens: make([]string, 0),
Dictionary: make([]string, 0),
LocalizedAttributes: []*LocalizedAttributes{
{
Locales: []Locate{JPN, ENG},
AttributePatterns: []string{"*_ja"},
},
},
},
},
{
Expand Down Expand Up @@ -3687,3 +3703,56 @@ func Test_ProximityPrecision(t *testing.T) {
require.NoError(t, err)
require.Equal(t, ByWord, got)
}

func Test_LocalizedAttributes(t *testing.T) {
c := setup(t, "")
t.Cleanup(cleanup(c))

indexID := "newIndexUID"
i := c.Index(indexID)
taskInfo, err := c.CreateIndex(&IndexConfig{Uid: indexID})
require.NoError(t, err)
testWaitForTask(t, i, taskInfo)

defer t.Cleanup(cleanup(c))

t.Run("Test valid locate", func(t *testing.T) {
got, err := i.GetLocalizedAttributes()
require.NoError(t, err)
require.Len(t, got, 0)

localized := &LocalizedAttributes{
Locales: []Locate{JPN, ENG},
AttributePatterns: []string{"*_ja"},
}

task, err := i.UpdateLocalizedAttributes([]*LocalizedAttributes{localized})
require.NoError(t, err)
testWaitForTask(t, i, task)

got, err = i.GetLocalizedAttributes()
require.NoError(t, err)
require.NotNil(t, got)

require.Equal(t, localized.Locales, got[0].Locales)
require.Equal(t, localized.AttributePatterns, got[0].AttributePatterns)

task, err = i.ResetLocalizedAttributes()
require.NoError(t, err)
testWaitForTask(t, i, task)

got, err = i.GetLocalizedAttributes()
require.NoError(t, err)
require.Len(t, got, 0)
})

t.Run("Test invalid locate", func(t *testing.T) {
invalidLocalized := &LocalizedAttributes{
Locales: []Locate{"foo"},
AttributePatterns: []string{"*_ja"},
}

_, err := i.UpdateLocalizedAttributes([]*LocalizedAttributes{invalidLocalized})
require.Error(t, err)
})
}
82 changes: 82 additions & 0 deletions locate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package meilisearch

// Locate is localized attributes for index in search
//
// https://www.meilisearch.com/docs/reference/api/settings#localized-attributes-object
type Locate string

const (
EPO Locate = "epo" // EPO is Esperanto
ENG Locate = "eng" // ENG is English
RUS Locate = "rus" // RUS is Russian
CMN Locate = "cmn" // CMN is Mandarin Chinese
SPA Locate = "spa" // SPA is Spanish
POR Locate = "por" // POR is Portuguese
ITA Locate = "ita" // ITA is Italian
BEN Locate = "ben" // BEN is Bengali
FRA Locate = "fra" // FRA is French
DEU Locate = "deu" // DEU is German
UKR Locate = "ukr" // UKR is Ukrainian
KAT Locate = "kat" // KAT is Georgian
ARA Locate = "ara" // ARA is Arabic
HIN Locate = "hin" // HIN is Hindi
JPN Locate = "jpn" // JPN is Japanese
HEB Locate = "heb" // HEB is Hebrew
YID Locate = "yid" // YID is Yiddish
POL Locate = "pol" // POL is Polish
AMH Locate = "amh" // AMH is Amharic
JAV Locate = "jav" // JAV is Javanese
KOR Locate = "kor" // KOR is Korean
NOB Locate = "nob" // NOB is Norwegian Bokmål
DAN Locate = "dan" // DAN is Danish
SWE Locate = "swe" // SWE is Swedish
FIN Locate = "fin" // FIN is Finnish
TUR Locate = "tur" // TUR is Turkish
NLD Locate = "nld" // NLD is Dutch
HUN Locate = "hun" // HUN is Hungarian
CES Locate = "ces" // CES is Czech
ELL Locate = "ell" // ELL is Greek
BUL Locate = "bul" // BUL is Bulgarian
BEL Locate = "bel" // BEL is Belarusian
MAR Locate = "mar" // MAR is Marathi
KAN Locate = "kan" // KAN is Kannada
RON Locate = "ron" // RON is Romanian
SLV Locate = "slv" // SLV is Slovenian
HRV Locate = "hrv" // HRV is Croatian
SRP Locate = "srp" // SRP is Serbian
MKD Locate = "mkd" // MKD is Macedonian
LIT Locate = "lit" // LIT is Lithuanian
LAV Locate = "lav" // LAV is Latvian
EST Locate = "est" // EST is Estonian
TAM Locate = "tam" // TAM is Tamil
VIE Locate = "vie" // VIE is Vietnamese
URD Locate = "urd" // URD is Urdu
THA Locate = "tha" // THA is Thai
GUJ Locate = "guj" // GUJ is Gujarati
UZB Locate = "uzb" // UZB is Uzbek
PAN Locate = "pan" // PAN is Punjabi
AZE Locate = "aze" // AZE is Azerbaijani
IND Locate = "ind" // IND is Indonesian
TEL Locate = "tel" // TEL is Telugu
PES Locate = "pes" // PES is Persian
MAL Locate = "mal" // MAL is Malayalam
ORI Locate = "ori" // ORI is Odia
MYA Locate = "mya" // MYA is Burmese
NEP Locate = "nep" // NEP is Nepali
SIN Locate = "sin" // SIN is Sinhala
KHM Locate = "khm" // KHM is Khmer
TUK Locate = "tuk" // TUK is Turkmen
AKA Locate = "aka" // AKA is Akan
ZUL Locate = "zul" // ZUL is Zulu
SNA Locate = "sna" // SNA is Shona
AFR Locate = "afr" // AFR is Afrikaans
LAT Locate = "lat" // LAT is Latin
SLK Locate = "slk" // SLK is Slovak
CAT Locate = "cat" // CAT is Catalan
TGL Locate = "tgl" // TGL is Tagalog
HYE Locate = "hye" // HYE is Armenian
)

func (l Locate) String() string {
return string(l)
}
1 change: 1 addition & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ func setUpIndexForFaceting(client ServiceManager) {
{BookID: 921, Title: "The Brothers Karamazov", Tag: "Novel", Year: 1879},
{BookID: 1032, Title: "Crime and Punishment", Tag: "Crime fiction", Year: 1866},
{BookID: 1039, Title: "The Girl in the white shirt", Tag: "white shirt", Year: 1999},
{BookID: 1050, Title: "星の王子さま", Tag: "物語", Year: 1943},
}
task, err := idx.AddDocuments(booksTest)
if err != nil {
Expand Down
9 changes: 9 additions & 0 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ const (
HuffmanOnlyCompression EncodingCompressionLevel = -2
ConstantCompression EncodingCompressionLevel = -2
StatelessCompression EncodingCompressionLevel = -3

nullBody = "null"
)

func (c ContentEncoding) String() string { return string(c) }
Expand Down Expand Up @@ -80,12 +82,18 @@ type Settings struct {
Synonyms map[string][]string `json:"synonyms,omitempty"`
FilterableAttributes []string `json:"filterableAttributes,omitempty"`
SortableAttributes []string `json:"sortableAttributes,omitempty"`
LocalizedAttributes []*LocalizedAttributes `json:"localizedAttributes,omitempty"`
TypoTolerance *TypoTolerance `json:"typoTolerance,omitempty"`
Pagination *Pagination `json:"pagination,omitempty"`
Faceting *Faceting `json:"faceting,omitempty"`
Embedders map[string]Embedder `json:"embedders,omitempty"`
}

type LocalizedAttributes struct {
Locales []Locate `json:"locales,omitempty"`
AttributePatterns []string `json:"attributePatterns,omitempty"`
}

// TypoTolerance is the type that represents the typo tolerance setting in meilisearch
type TypoTolerance struct {
Enabled bool `json:"enabled"`
Expand Down Expand Up @@ -429,6 +437,7 @@ type SearchRequest struct {
RetrieveVectors bool `json:"retrieveVectors,omitempty"`
RankingScoreThreshold float64 `json:"rankingScoreThreshold,omitempty"`
FederationOptions *SearchFederationOptions `json:"federationOptions,omitempty"`
Locate []Locate `json:"locales,omitempty"`
}

type SearchFederationOptions struct {
Expand Down
Loading

0 comments on commit 1f4a74c

Please sign in to comment.