Skip to content

Commit

Permalink
[add] Added CreateIndexWithIndexDefinition
Browse files Browse the repository at this point in the history
  • Loading branch information
filipecosta90 committed Aug 8, 2020
1 parent 9708884 commit 55d65fa
Show file tree
Hide file tree
Showing 6 changed files with 218 additions and 7 deletions.
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ examples: get
--tls-ca-cert-file $(TLS_CACERT) \
--host $(REDISEARCH_TEST_HOST)

test: get
fmt:
$(GOFMT) ./...

test: get fmt
$(GOTEST) -race -covermode=atomic ./...

coverage: get test
Expand Down
22 changes: 18 additions & 4 deletions redisearch/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,29 @@ func NewClientFromPool(pool *redis.Pool, name string) *Client {
return ret
}

// CreateIndex configues the index and creates it on redis
func (i *Client) CreateIndex(s *Schema) (err error) {
// CreateIndex configures the index and creates it on redis
func (i *Client) CreateIndex(schema *Schema) (err error) {
return i.indexWithDefinition(i.name, schema, nil, err)
}

// CreateIndexWithIndexDefinition configures the index and creates it on redis
// IndexDefinition is used to define a index definition for automatic indexing on Hash update
func (i *Client) CreateIndexWithIndexDefinition(schema *Schema, definition *IndexDefinition) (err error) {
return i.indexWithDefinition(i.name, schema, definition, err)
}

// internal method
func (i *Client) indexWithDefinition(indexName string, schema *Schema, definition *IndexDefinition, errIn error) (err error) {
err = errIn
args := redis.Args{i.name}
if definition != nil {
args = definition.Serialize(args)
}
// Set flags based on options
args, err = SerializeSchema(s, args)
args, err = SerializeSchema(schema, args)
if err != nil {
return
}

conn := i.pool.Get()
defer conn.Close()
_, err = conn.Do("FT.CREATE", args...)
Expand Down
43 changes: 43 additions & 0 deletions redisearch/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -614,3 +614,46 @@ func TestClient_GetRediSearchVersion(t *testing.T) {
_, err := c.getRediSearchVersion()
assert.Nil(t, err)
}

func TestClient_CreateIndexWithIndexDefinition(t *testing.T) {
i := createClient("index-definition-test")
version, err := i.getRediSearchVersion()
assert.Nil(t, err)
if version >= 20000 {

type args struct {
schema *Schema
definition *IndexDefinition
}
tests := []struct {
name string
args args
wantErr bool
}{
{"no-indexDefinition", args{NewSchema(DefaultOptions).
AddField(NewTextField("name")).
AddField(NewTextField("addr")), nil}, false},
{"default-indexDefinition", args{NewSchema(DefaultOptions).
AddField(NewTextField("name")).
AddField(NewTextField("addr")), NewIndexDefinition()}, false},
{"score-indexDefinition", args{NewSchema(DefaultOptions).
AddField(NewTextField("name")).
AddField(NewTextField("addr")), NewIndexDefinition().SetScore(0.25)}, false},
{"language-indexDefinition", args{NewSchema(DefaultOptions).
AddField(NewTextField("name")).
AddField(NewTextField("addr")), NewIndexDefinition().SetLanguage("portuguese")}, false},
{"language_field-indexDefinition", args{NewSchema(DefaultOptions).
AddField(NewTextField("name")).
AddField(NewTextField("lang")).
AddField(NewTextField("addr")), NewIndexDefinition().SetLanguageField("lang")}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := i.CreateIndexWithIndexDefinition(tt.args.schema, tt.args.definition); (err != nil) != tt.wantErr {
t.Errorf("CreateIndexWithIndexDefinition() error = %v, wantErr %v", err, tt.wantErr)
}
teardown(i)
})
}
}
}
2 changes: 1 addition & 1 deletion redisearch/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type Filter struct {
Options interface{}
}

// Filter the results to a given radius from lon and lat. Radius is given as a number and units
// FilterExpression the results to a given radius from lon and lat. Radius is given as a number and units
type GeoFilterOptions struct {
Lon float64
Lat float64
Expand Down
115 changes: 114 additions & 1 deletion redisearch/index.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package redisearch

import "github.com/gomodule/redigo/redis"
import (
"github.com/gomodule/redigo/redis"
)

// IndexInfo - Structure showing information about an existing index
type IndexInfo struct {
Expand All @@ -22,6 +24,117 @@ type IndexInfo struct {
PercentIndexed float64 `redis:"percent_indexed"`
}

// IndexDefinition is used to define a index definition for automatic indexing on Hash update
// This is only valid for >= RediSearch 2.0
type IndexDefinition struct {
IndexOn string
Async bool
Prefix []string
FilterExpression string
Language string
LanguageField string
Score float64
ScoreField string
PayloadField string
}

// This is only valid for >= RediSearch 2.0
func NewIndexDefinition() *IndexDefinition {
prefixArray := make([]string, 0)
return &IndexDefinition{"HASH", false, prefixArray, "", "", "", -1, "", ""}
}

// This is only valid for >= RediSearch 2.0
func (defintion *IndexDefinition) SetAsync(value bool) (outDef *IndexDefinition) {
outDef = defintion
outDef.Async = value
return
}

// This is only valid for >= RediSearch 2.0
func (defintion *IndexDefinition) AddPrefix(prefix string) (outDef *IndexDefinition) {
outDef = defintion
outDef.Prefix = append(outDef.Prefix, prefix)
return
}

func (defintion *IndexDefinition) SetFilterExpression(value string) (outDef *IndexDefinition) {
outDef = defintion
outDef.FilterExpression = value
return
}

// This is only valid for >= RediSearch 2.0
func (defintion *IndexDefinition) SetLanguage(value string) (outDef *IndexDefinition) {
outDef = defintion
outDef.Language = value
return
}

// This is only valid for >= RediSearch 2.0
func (defintion *IndexDefinition) SetLanguageField(value string) (outDef *IndexDefinition) {
outDef = defintion
outDef.LanguageField = value
return
}

// This is only valid for >= RediSearch 2.0
func (defintion *IndexDefinition) SetScore(value float64) (outDef *IndexDefinition) {
outDef = defintion
outDef.Score = value
return
}

// This is only valid for >= RediSearch 2.0
func (defintion *IndexDefinition) SetScoreField(value string) (outDef *IndexDefinition) {
outDef = defintion
outDef.ScoreField = value
return
}

// This is only valid for >= RediSearch 2.0
func (defintion *IndexDefinition) SetPayloadField(value string) (outDef *IndexDefinition) {
outDef = defintion
outDef.PayloadField = value
return
}

// This is only valid for >= RediSearch 2.0
func (defintion *IndexDefinition) Serialize(args redis.Args) redis.Args {
args = append(args, "ON", defintion.IndexOn)
if defintion.Async {
args = append(args, "ASYNC")
}
if len(defintion.Prefix) > 0 {
args = append(args, "PREFIX", len(defintion.Prefix))
for _, p := range defintion.Prefix {
args = append(args, p)
}
}
if defintion.FilterExpression != "" {
args = append(args, "FILTER", defintion.FilterExpression)
}
if defintion.Language != "" {
args = append(args, "LANGUAGE", defintion.Language)
}

if defintion.LanguageField != "" {
args = append(args, "LANGUAGE_FIELD", defintion.LanguageField)
}

if defintion.Score >= 0.0 && defintion.Score <= 1.0 {
args = append(args, "SCORE", defintion.Score)
}

if defintion.ScoreField != "" {
args = append(args, "SCORE_FIELD", defintion.ScoreField)
}
if defintion.PayloadField != "" {
args = append(args, "PAYLOAD_FIELD", defintion.PayloadField)
}
return args
}

func SerializeIndexingOptions(opts IndexingOptions, args redis.Args) redis.Args {
// apply options
if opts.NoSave {
Expand Down
39 changes: 39 additions & 0 deletions redisearch/index_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package redisearch

import (
"github.com/gomodule/redigo/redis"
"reflect"
"testing"
)

func TestIndexDefinition_Serialize(t *testing.T) {
type fields struct {
Definition *IndexDefinition
}
type args struct {
args redis.Args
}
tests := []struct {
name string
fields fields
args args
want redis.Args
}{
{"default", fields{NewIndexDefinition()}, args{redis.Args{}}, redis.Args{"ON", "HASH"}},
{"default+score", fields{NewIndexDefinition().SetScore(0.75)}, args{redis.Args{}}, redis.Args{"ON", "HASH", "SCORE", 0.75}},
{"default+score_field", fields{NewIndexDefinition().SetScoreField("myscore")}, args{redis.Args{}}, redis.Args{"ON", "HASH", "SCORE_FIELD", "myscore"}},
{"default+language", fields{NewIndexDefinition().SetLanguage("portuguese")}, args{redis.Args{}}, redis.Args{"ON", "HASH", "LANGUAGE", "portuguese"}},
{"default+language_field", fields{NewIndexDefinition().SetLanguageField("mylanguage")}, args{redis.Args{}}, redis.Args{"ON", "HASH", "LANGUAGE_FIELD", "mylanguage"}},
{"default+prefix", fields{NewIndexDefinition().AddPrefix("products:*")}, args{redis.Args{}}, redis.Args{"ON", "HASH", "PREFIX", 1, "products:*"}},
{"default+payload_field", fields{NewIndexDefinition().SetPayloadField("products_description")}, args{redis.Args{}}, redis.Args{"ON", "HASH", "PAYLOAD_FIELD", "products_description"}},
{"default+filter", fields{NewIndexDefinition().SetFilterExpression("@score:[0 50]")}, args{redis.Args{}}, redis.Args{"ON", "HASH", "FILTER", "@score:[0 50]"}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defintion := tt.fields.Definition
if got := defintion.Serialize(tt.args.args); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Serialize() = %v, want %v", got, tt.want)
}
})
}
}

0 comments on commit 55d65fa

Please sign in to comment.