mirror of
https://github.com/redis/go-redis.git
synced 2026-10-28 08:24:54 +08:00
fix(search): emit SORTABLE after field options (#4199)
FT.CREATE stops reading type-specific field options at SORTABLE, UNF and NOINDEX. A field with Sortable and Weight, Separator, CaseSensitive, PhoneticMatcher, WithSuffixtrie, IndexEmpty or IndexMissing was rejected by the server. Emit SORTABLE, UNF and NOINDEX after the other options.
This commit is contained in:
1 parent
29bfa68281
commit
7852b431b5
2 files changed
+71
-9
No files matched your search
+11
-9
@@ -1656,15 +1656,6 @@ func (c cmdable) FTCreate(ctx context.Context, index string, options *FTCreateOp
|
||||
if schema.NoStem {
|
||||
args = append(args, "NOSTEM")
|
||||
}
|
||||
if schema.Sortable {
|
||||
args = append(args, "SORTABLE")
|
||||
}
|
||||
if schema.UNF {
|
||||
args = append(args, "UNF")
|
||||
}
|
||||
if schema.NoIndex {
|
||||
args = append(args, "NOINDEX")
|
||||
}
|
||||
if schema.PhoneticMatcher != "" {
|
||||
args = append(args, "PHONETIC", schema.PhoneticMatcher)
|
||||
}
|
||||
@@ -1686,6 +1677,17 @@ func (c cmdable) FTCreate(ctx context.Context, index string, options *FTCreateOp
|
||||
if schema.IndexMissing {
|
||||
args = append(args, "INDEXMISSING")
|
||||
}
|
||||
// FT.CREATE stops reading type-specific options at SORTABLE, UNF and
|
||||
// NOINDEX, so they must come last.
|
||||
if schema.Sortable {
|
||||
args = append(args, "SORTABLE")
|
||||
}
|
||||
if schema.UNF {
|
||||
args = append(args, "UNF")
|
||||
}
|
||||
if schema.NoIndex {
|
||||
args = append(args, "NOINDEX")
|
||||
}
|
||||
}
|
||||
cmd := NewStatusCmd(ctx, args...)
|
||||
_ = c(ctx, cmd)
|
||||
|
||||
@@ -524,6 +524,66 @@ func TestFTCreateHNSWRerank_Args(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestFTCreateSortableAfterFieldOptions verifies that SORTABLE, UNF and
|
||||
// NOINDEX follow the type-specific field options. FT.CREATE reads no
|
||||
// type-specific option after them, so "TEXT SORTABLE WEIGHT 2" fails.
|
||||
func TestFTCreateSortableAfterFieldOptions(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
schema *FieldSchema
|
||||
want []interface{}
|
||||
}{
|
||||
{
|
||||
name: "text",
|
||||
schema: &FieldSchema{
|
||||
FieldName: "t", FieldType: SearchFieldTypeText,
|
||||
NoStem: true, PhoneticMatcher: "dm:en", Weight: 2, WithSuffixtrie: true,
|
||||
IndexEmpty: true, IndexMissing: true, Sortable: true, UNF: true,
|
||||
},
|
||||
want: []interface{}{
|
||||
"FT.CREATE", "idx", "SCHEMA", "t", "TEXT", "NOSTEM", "PHONETIC", "dm:en",
|
||||
"WEIGHT", float64(2), "WITHSUFFIXTRIE", "INDEXEMPTY", "INDEXMISSING",
|
||||
"SORTABLE", "UNF",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "tag",
|
||||
schema: &FieldSchema{
|
||||
FieldName: "g", FieldType: SearchFieldTypeTag,
|
||||
Separator: ";", CaseSensitive: true, Sortable: true, NoIndex: true,
|
||||
},
|
||||
want: []interface{}{
|
||||
"FT.CREATE", "idx", "SCHEMA", "g", "TAG", "SEPARATOR", ";", "CASESENSITIVE",
|
||||
"SORTABLE", "NOINDEX",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "numeric",
|
||||
schema: &FieldSchema{
|
||||
FieldName: "n", FieldType: SearchFieldTypeNumeric,
|
||||
IndexMissing: true, Sortable: true,
|
||||
},
|
||||
want: []interface{}{
|
||||
"FT.CREATE", "idx", "SCHEMA", "n", "NUMERIC", "INDEXMISSING", "SORTABLE",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
m := &mockCmdable{}
|
||||
c := m.asCmdable()
|
||||
cmd := c.FTCreate(context.Background(), "idx", nil, tt.schema)
|
||||
if cmd.Err() != nil {
|
||||
t.Fatalf("unexpected error: %v", cmd.Err())
|
||||
}
|
||||
if !reflect.DeepEqual(cmd.Args(), tt.want) {
|
||||
t.Errorf("args mismatch\n got: %#v\nwant: %#v", cmd.Args(), tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestFTCreateHNSWCompression_Args verifies the COMPRESSION and
|
||||
// TRAINING_THRESHOLD attributes (Redis 8.12+, scalar-quantized HNSW) are
|
||||
// emitted as key-value pairs counted in the attribute-count token.
|
||||
|
||||
Reference in new issue
Block a user