Skip to content

Commit 42408e1

Browse files
NewSchema fix and extended testing for SerializeSchema (#58)
* NewSchema fix and extended testing for SerializeSchema
1 parent b4cac87 commit 42408e1

File tree

3 files changed

+200
-90
lines changed

3 files changed

+200
-90
lines changed

redisearch/query.go

Lines changed: 0 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package redisearch
22

33
import (
4-
"errors"
5-
"fmt"
6-
74
"github.com/gomodule/redigo/redis"
85
)
96

@@ -300,93 +297,6 @@ func (q *Query) SummarizeOptions(opts SummaryOptions) *Query {
300297
return q
301298
}
302299

303-
func SerializeSchema(s *Schema, args redis.Args) (redis.Args, error) {
304-
if s.Options.NoFieldFlags {
305-
args = append(args, "NOFIELDS")
306-
}
307-
if s.Options.NoFrequencies {
308-
args = append(args, "NOFREQS")
309-
}
310-
if s.Options.NoOffsetVectors {
311-
args = append(args, "NOOFFSETS")
312-
}
313-
if s.Options.Stopwords != nil {
314-
args = args.Add("STOPWORDS", len(s.Options.Stopwords))
315-
if len(s.Options.Stopwords) > 0 {
316-
args = args.AddFlat(s.Options.Stopwords)
317-
}
318-
}
319-
320-
args = append(args, "SCHEMA")
321-
for _, f := range s.Fields {
322-
323-
switch f.Type {
324-
case TextField:
325-
326-
args = append(args, f.Name, "TEXT")
327-
if f.Options != nil {
328-
opts, ok := f.Options.(TextFieldOptions)
329-
if !ok {
330-
return nil, errors.New("Invalid text field options type")
331-
}
332-
333-
if opts.Weight != 0 && opts.Weight != 1 {
334-
args = append(args, "WEIGHT", opts.Weight)
335-
}
336-
if opts.NoStem {
337-
args = append(args, "NOSTEM")
338-
}
339-
340-
if opts.Sortable {
341-
args = append(args, "SORTABLE")
342-
}
343-
344-
if opts.NoIndex {
345-
args = append(args, "NOINDEX")
346-
}
347-
}
348-
349-
case NumericField:
350-
args = append(args, f.Name, "NUMERIC")
351-
if f.Options != nil {
352-
opts, ok := f.Options.(NumericFieldOptions)
353-
if !ok {
354-
return nil, errors.New("Invalid numeric field options type")
355-
}
356-
357-
if opts.Sortable {
358-
args = append(args, "SORTABLE")
359-
}
360-
if opts.NoIndex {
361-
args = append(args, "NOINDEX")
362-
}
363-
}
364-
case TagField:
365-
args = append(args, f.Name, "TAG")
366-
if f.Options != nil {
367-
opts, ok := f.Options.(TagFieldOptions)
368-
if !ok {
369-
return nil, errors.New("Invalid tag field options type")
370-
}
371-
if opts.Separator != 0 {
372-
args = append(args, "SEPARATOR", fmt.Sprintf("%c", opts.Separator))
373-
374-
}
375-
if opts.Sortable {
376-
args = append(args, "SORTABLE")
377-
}
378-
if opts.NoIndex {
379-
args = append(args, "NOINDEX")
380-
}
381-
}
382-
default:
383-
return nil, fmt.Errorf("Unsupported field type %v", f.Type)
384-
}
385-
386-
}
387-
return args, nil
388-
}
389-
390300
// IndexOptions indexes multiple documents on the index, with optional Options passed to options
391301
func (i *Client) IndexOptions(opts IndexingOptions, docs ...Document) error {
392302

redisearch/schema.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
package redisearch
22

3+
import (
4+
"errors"
5+
"fmt"
6+
"github.com/gomodule/redigo/redis"
7+
)
8+
39
// FieldType is an enumeration of field/property types
410
type FieldType int
511

@@ -163,6 +169,7 @@ type Schema struct {
163169
func NewSchema(opts Options) *Schema {
164170
return &Schema{
165171
Fields: []Field{},
172+
Options: opts,
166173
}
167174
}
168175

@@ -174,3 +181,91 @@ func (m *Schema) AddField(f Field) *Schema {
174181
m.Fields = append(m.Fields, f)
175182
return m
176183
}
184+
185+
186+
func SerializeSchema(s *Schema, args redis.Args) (redis.Args, error) {
187+
if s.Options.NoFieldFlags {
188+
args = append(args, "NOFIELDS")
189+
}
190+
if s.Options.NoFrequencies {
191+
args = append(args, "NOFREQS")
192+
}
193+
if s.Options.NoOffsetVectors {
194+
args = append(args, "NOOFFSETS")
195+
}
196+
if s.Options.Stopwords != nil {
197+
args = args.Add("STOPWORDS", len(s.Options.Stopwords))
198+
if len(s.Options.Stopwords) > 0 {
199+
args = args.AddFlat(s.Options.Stopwords)
200+
}
201+
}
202+
203+
args = append(args, "SCHEMA")
204+
for _, f := range s.Fields {
205+
206+
switch f.Type {
207+
case TextField:
208+
209+
args = append(args, f.Name, "TEXT")
210+
if f.Options != nil {
211+
opts, ok := f.Options.(TextFieldOptions)
212+
if !ok {
213+
return nil, errors.New("Invalid text field options type")
214+
}
215+
216+
if opts.Weight != 0 && opts.Weight != 1 {
217+
args = append(args, "WEIGHT", opts.Weight)
218+
}
219+
if opts.NoStem {
220+
args = append(args, "NOSTEM")
221+
}
222+
223+
if opts.Sortable {
224+
args = append(args, "SORTABLE")
225+
}
226+
227+
if opts.NoIndex {
228+
args = append(args, "NOINDEX")
229+
}
230+
}
231+
232+
case NumericField:
233+
args = append(args, f.Name, "NUMERIC")
234+
if f.Options != nil {
235+
opts, ok := f.Options.(NumericFieldOptions)
236+
if !ok {
237+
return nil, errors.New("Invalid numeric field options type")
238+
}
239+
240+
if opts.Sortable {
241+
args = append(args, "SORTABLE")
242+
}
243+
if opts.NoIndex {
244+
args = append(args, "NOINDEX")
245+
}
246+
}
247+
case TagField:
248+
args = append(args, f.Name, "TAG")
249+
if f.Options != nil {
250+
opts, ok := f.Options.(TagFieldOptions)
251+
if !ok {
252+
return nil, errors.New("Invalid tag field options type")
253+
}
254+
if opts.Separator != 0 {
255+
args = append(args, "SEPARATOR", fmt.Sprintf("%c", opts.Separator))
256+
257+
}
258+
if opts.Sortable {
259+
args = append(args, "SORTABLE")
260+
}
261+
if opts.NoIndex {
262+
args = append(args, "NOINDEX")
263+
}
264+
}
265+
default:
266+
return nil, fmt.Errorf("Unsupported field type %v", f.Type)
267+
}
268+
269+
}
270+
return args, nil
271+
}

redisearch/schema_test.go

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package redisearch
2+
3+
import (
4+
"github.com/gomodule/redigo/redis"
5+
"github.com/stretchr/testify/assert"
6+
"reflect"
7+
"testing"
8+
)
9+
10+
func TestNewSchema(t *testing.T) {
11+
type args struct {
12+
opts Options
13+
}
14+
tests := []struct {
15+
name string
16+
args args
17+
want *Schema
18+
}{
19+
{"default", args{DefaultOptions}, &Schema{Fields: []Field{},
20+
Options: DefaultOptions}},
21+
{"custom-stopwords", args{Options{Stopwords: []string{"custom"}}}, &Schema{Fields: []Field{},
22+
Options: Options{Stopwords: []string{"custom"}}}},
23+
{"no-frequencies", args{Options{NoFrequencies: true}}, &Schema{Fields: []Field{},
24+
Options: Options{NoFrequencies: true}}},
25+
}
26+
for _, tt := range tests {
27+
t.Run(tt.name, func(t *testing.T) {
28+
if got := NewSchema(tt.args.opts); !reflect.DeepEqual(got, tt.want) {
29+
t.Errorf("NewSchema() = %v, want %v", got, tt.want)
30+
}
31+
})
32+
}
33+
}
34+
35+
func TestSerializeSchema(t *testing.T) {
36+
type args struct {
37+
s *Schema
38+
args redis.Args
39+
}
40+
tests := []struct {
41+
name string
42+
args args
43+
want redis.Args
44+
wantErr bool
45+
}{
46+
{"default-args", args{NewSchema(DefaultOptions), redis.Args{}}, redis.Args{"SCHEMA"}, false},
47+
{"no-frequencies", args{NewSchema(Options{NoFrequencies: true}), redis.Args{}}, redis.Args{"NOFREQS", "SCHEMA"}, false},
48+
{"no-fields", args{NewSchema(Options{NoFieldFlags: true}), redis.Args{}}, redis.Args{"NOFIELDS", "SCHEMA"}, false},
49+
{"custom-stopwords", args{NewSchema(Options{Stopwords: []string{"custom"}}), redis.Args{}}, redis.Args{"STOPWORDS", 1, "custom", "SCHEMA"}, false},
50+
{"no-offsets", args{NewSchema(Options{NoOffsetVectors: true}), redis.Args{}}, redis.Args{"NOOFFSETS", "SCHEMA"}, false},
51+
{"default-and-numeric", args{NewSchema(DefaultOptions).AddField(NewNumericField("numeric-field")), redis.Args{}}, redis.Args{"SCHEMA", "numeric-field", "NUMERIC"}, false},
52+
{"default-and-numeric-sortable", args{NewSchema(DefaultOptions).AddField(NewSortableNumericField("numeric-field")), redis.Args{}}, redis.Args{"SCHEMA", "numeric-field", "NUMERIC", "SORTABLE"}, false},
53+
{"default-and-numeric-with-options-noindex", args{NewSchema(DefaultOptions).AddField(NewNumericFieldOptions("numeric-field", NumericFieldOptions{NoIndex: true, Sortable: false})), redis.Args{}}, redis.Args{"SCHEMA", "numeric-field", "NUMERIC", "NOINDEX"}, false},
54+
{"default-and-text", args{NewSchema(DefaultOptions).AddField(NewTextField("text-field")), redis.Args{}}, redis.Args{"SCHEMA", "text-field", "TEXT"}, false},
55+
{"default-and-sortable-text-field", args{NewSchema(DefaultOptions).AddField(NewSortableTextField("text-field", 10)), redis.Args{}}, redis.Args{"SCHEMA", "text-field", "TEXT", "WEIGHT", float32(10.0), "SORTABLE"}, false},
56+
{"default-and-text-with-options", args{NewSchema(DefaultOptions).AddField(NewTextFieldOptions("text-field", TextFieldOptions{Weight: 5.0, Sortable: true, NoStem: false, NoIndex: false})), redis.Args{}}, redis.Args{"SCHEMA", "text-field", "TEXT", "WEIGHT", float32(5.0), "SORTABLE"}, false},
57+
{"default-and-tag", args{NewSchema(DefaultOptions).AddField(NewTagField("tag-field")), redis.Args{}}, redis.Args{"SCHEMA", "tag-field", "TAG", "SEPARATOR", ","}, false},
58+
{"default-and-tag-with-options", args{NewSchema(DefaultOptions).AddField(NewTagFieldOptions("tag-field", TagFieldOptions{Sortable: true, NoIndex: false, Separator: byte(',')})), redis.Args{}}, redis.Args{"SCHEMA", "tag-field", "TAG", "SEPARATOR", ",", "SORTABLE"}, false},
59+
{"error-unsupported", args{NewSchema(DefaultOptions).AddField(Field{Type: 10}), redis.Args{}}, nil, true},
60+
}
61+
for _, tt := range tests {
62+
t.Run(tt.name, func(t *testing.T) {
63+
got, err := SerializeSchema(tt.args.s, tt.args.args)
64+
if (err != nil) != tt.wantErr {
65+
t.Errorf("SerializeSchema() error = %v, wantErr %v", err, tt.wantErr)
66+
return
67+
}
68+
if !reflect.DeepEqual(got, tt.want) {
69+
t.Errorf("SerializeSchema() got = %v, want %v", got, tt.want)
70+
}
71+
assert.Equal(t, got, tt.want)
72+
})
73+
}
74+
}
75+
76+
func TestSchema_AddField(t *testing.T) {
77+
type fields struct {
78+
Fields []Field
79+
Options Options
80+
}
81+
type args struct {
82+
f Field
83+
}
84+
tests := []struct {
85+
name string
86+
fields fields
87+
args args
88+
want *Schema
89+
}{
90+
{"nil", fields{nil, DefaultOptions}, args{NewTextField("text-field")}, &Schema{Fields: []Field{NewTextField("text-field")}, Options: DefaultOptions}},
91+
{"empty", fields{[]Field{}, DefaultOptions}, args{NewTextField("text-field")}, &Schema{Fields: []Field{NewTextField("text-field")}, Options: DefaultOptions}},
92+
{"1-field", fields{[]Field{NewTextField("field1")}, DefaultOptions}, args{NewTextField("field2")}, &Schema{Fields: []Field{NewTextField("field1"), NewTextField("field2")}, Options: DefaultOptions}},
93+
}
94+
for _, tt := range tests {
95+
t.Run(tt.name, func(t *testing.T) {
96+
m := &Schema{
97+
Fields: tt.fields.Fields,
98+
Options: tt.fields.Options,
99+
}
100+
if got := m.AddField(tt.args.f); !reflect.DeepEqual(got, tt.want) {
101+
t.Errorf("AddField() = %v, want %v", got, tt.want)
102+
}
103+
})
104+
}
105+
}

0 commit comments

Comments
 (0)