Skip to content

Commit b00f7f9

Browse files
committed
feat: support vectorset
1 parent 43e7fb5 commit b00f7f9

File tree

4 files changed

+662
-0
lines changed

4 files changed

+662
-0
lines changed

command.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5615,3 +5615,58 @@ func (cmd *MonitorCmd) Stop() {
56155615
defer cmd.mu.Unlock()
56165616
cmd.status = monitorStatusStop
56175617
}
5618+
5619+
type MapStringFloatCmd struct {
5620+
baseCmd
5621+
5622+
val map[string]float64
5623+
}
5624+
5625+
var _ Cmder = (*MapStringFloatCmd)(nil)
5626+
5627+
func NewMapStringFloatCmd(ctx context.Context, args ...interface{}) *MapStringFloatCmd {
5628+
return &MapStringFloatCmd{
5629+
baseCmd: baseCmd{
5630+
ctx: ctx,
5631+
args: args,
5632+
},
5633+
}
5634+
}
5635+
5636+
func (cmd *MapStringFloatCmd) SetVal(val map[string]float64) {
5637+
cmd.val = val
5638+
}
5639+
5640+
func (cmd *MapStringFloatCmd) Val() map[string]float64 {
5641+
return cmd.val
5642+
}
5643+
5644+
func (cmd *MapStringFloatCmd) Result() (map[string]float64, error) {
5645+
return cmd.val, cmd.err
5646+
}
5647+
5648+
func (cmd *MapStringFloatCmd) String() string {
5649+
return cmdString(cmd, cmd.val)
5650+
}
5651+
5652+
func (cmd *MapStringFloatCmd) readReply(rd *proto.Reader) error {
5653+
n, err := rd.ReadMapLen()
5654+
if err != nil {
5655+
return err
5656+
}
5657+
5658+
cmd.val = make(map[string]float64, n)
5659+
for i := 0; i < n; i++ {
5660+
key, err := rd.ReadString()
5661+
if err != nil {
5662+
return err
5663+
}
5664+
5665+
nn, err := rd.ReadFloat()
5666+
if err != nil {
5667+
return err
5668+
}
5669+
cmd.val[key] = nn
5670+
}
5671+
return nil
5672+
}

commands.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ type Cmdable interface {
234234
StreamCmdable
235235
TimeseriesCmdable
236236
JSONCmdable
237+
VectorSetCmdable
237238
}
238239

239240
type StatefulCmdable interface {

vectorset_commands.go

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
package redis
2+
3+
import (
4+
"context"
5+
"strconv"
6+
)
7+
8+
type VectorSetCmdable interface {
9+
VAdd(ctx context.Context, key, element string, val Vector) *BoolCmd
10+
VAddArgs(ctx context.Context, key, element string, val Vector, addArgs VAddArgs) *BoolCmd
11+
VCard(ctx context.Context, key string) *IntCmd
12+
VDim(ctx context.Context, key string) *IntCmd
13+
VEmb(ctx context.Context, key, element string, raw bool) *SliceCmd
14+
VGetAttr(ctx context.Context, key, element string) *StringCmd
15+
VInfo(ctx context.Context, key string) *MapStringInterfaceCmd
16+
VLinks(ctx context.Context, key, element string) *StringSliceCmd
17+
VLinksWithScores(ctx context.Context, key, element string) *MapStringFloatCmd
18+
VRandMember(ctx context.Context, key string) *StringCmd
19+
VRandMemberCount(ctx context.Context, key string, count int) *StringSliceCmd
20+
VRem(ctx context.Context, key, element string) *BoolCmd
21+
VSetAttr(ctx context.Context, key, element, attr string) *BoolCmd
22+
VSim(ctx context.Context, key string, val Vector) *StringSliceCmd
23+
VSimWithScores(ctx context.Context, key string, val Vector) *MapStringFloatCmd
24+
VSimArgs(ctx context.Context, key string, val Vector, args VSimArgs) *StringSliceCmd
25+
VSimArgsWithScores(ctx context.Context, key string, val Vector, args VSimArgs) *MapStringFloatCmd
26+
}
27+
28+
type Vector interface {
29+
Value() []any
30+
}
31+
32+
const (
33+
vectorFormatFP32 string = "FP32"
34+
vectorFormatValues string = "Values"
35+
)
36+
37+
type VectorFP32 struct {
38+
Val []byte
39+
}
40+
41+
func (v *VectorFP32) Value() []any {
42+
return []any{vectorFormatFP32, v.Val}
43+
}
44+
45+
var _ Vector = &VectorFP32{}
46+
47+
type VectorValues struct {
48+
Val []float64
49+
}
50+
51+
func (v *VectorValues) Value() []any {
52+
res := make([]any, 2+len(v.Val))
53+
res[0] = vectorFormatValues
54+
res[1] = len(v.Val)
55+
for i, v := range v.Val {
56+
res[2+i] = v
57+
}
58+
return res
59+
}
60+
61+
var _ Vector = &VectorValues{}
62+
63+
type VectorRef struct {
64+
Name string // the name of the referent vector
65+
}
66+
67+
func (v *VectorRef) Value() []any {
68+
return []any{"ele", v.Name}
69+
}
70+
71+
var _ Vector = &VectorRef{}
72+
73+
// `VADD key (FP32 | VALUES num) vector element`
74+
func (c cmdable) VAdd(ctx context.Context, key, element string, val Vector) *BoolCmd {
75+
return c.VAddArgs(ctx, key, element, val, VAddArgs{})
76+
}
77+
78+
type VAddArgs struct {
79+
// the REDUCE option must be passed immediately after the key
80+
Reduce int64
81+
Cas bool
82+
83+
// The NoQuant, Q8 and Bin options are mutually exclusive.
84+
NoQuant bool
85+
Q8 bool
86+
Bin bool
87+
88+
EF int64
89+
SetAttr string
90+
M int64
91+
}
92+
93+
func (v VAddArgs) reduce() int64 {
94+
return v.Reduce
95+
}
96+
97+
func (v VAddArgs) appendArgs(args []any) []any {
98+
if v.Cas {
99+
args = append(args, "cas")
100+
}
101+
102+
if v.NoQuant {
103+
args = append(args, "noquant")
104+
} else if v.Q8 {
105+
args = append(args, "q8")
106+
} else if v.Bin {
107+
args = append(args, "bin")
108+
}
109+
110+
if v.EF > 0 {
111+
args = append(args, "ef", strconv.FormatInt(v.EF, 10))
112+
}
113+
if len(v.SetAttr) > 0 {
114+
args = append(args, "setattr", v.SetAttr)
115+
}
116+
if v.M > 0 {
117+
args = append(args, "m", strconv.FormatInt(v.M, 10))
118+
}
119+
return args
120+
}
121+
122+
// `VADD key [REDUCE dim] (FP32 | VALUES num) vector element [CAS] [NOQUANT | Q8 | BIN] [EF build-exploration-factor] [SETATTR attributes] [M numlinks]`
123+
func (c cmdable) VAddArgs(ctx context.Context, key, element string, val Vector, addArgs VAddArgs) *BoolCmd {
124+
args := []any{"vadd", key}
125+
if addArgs.reduce() > 0 {
126+
args = append(args, "reduce", addArgs.reduce())
127+
}
128+
args = append(args, val.Value()...)
129+
args = append(args, element)
130+
args = addArgs.appendArgs(args)
131+
cmd := NewBoolCmd(ctx, args...)
132+
_ = c(ctx, cmd)
133+
return cmd
134+
}
135+
136+
// `VCARD key`
137+
func (c cmdable) VCard(ctx context.Context, key string) *IntCmd {
138+
cmd := NewIntCmd(ctx, "vcard", key)
139+
_ = c(ctx, cmd)
140+
return cmd
141+
}
142+
143+
// `VDIM key`
144+
func (c cmdable) VDim(ctx context.Context, key string) *IntCmd {
145+
cmd := NewIntCmd(ctx, "vdim", key)
146+
_ = c(ctx, cmd)
147+
return cmd
148+
}
149+
150+
// `VEMB key element [RAW]`
151+
func (c cmdable) VEmb(ctx context.Context, key, element string, raw bool) *SliceCmd {
152+
args := []any{"vemb", key, element}
153+
if raw {
154+
args = append(args, "raw")
155+
}
156+
cmd := NewSliceCmd(ctx, args...)
157+
_ = c(ctx, cmd)
158+
return cmd
159+
}
160+
161+
// `VGETATTR key element`
162+
func (c cmdable) VGetAttr(ctx context.Context, key, element string) *StringCmd {
163+
cmd := NewStringCmd(ctx, "vgetattr", key, element)
164+
_ = c(ctx, cmd)
165+
return cmd
166+
}
167+
168+
// `VINFO key`
169+
func (c cmdable) VInfo(ctx context.Context, key string) *MapStringInterfaceCmd {
170+
cmd := NewMapStringInterfaceCmd(ctx, "vinfo", key)
171+
_ = c(ctx, cmd)
172+
return cmd
173+
}
174+
175+
// `VLINKS key element`
176+
func (c cmdable) VLinks(ctx context.Context, key, element string) *StringSliceCmd {
177+
cmd := NewStringSliceCmd(ctx, "vlinks", key, element)
178+
_ = c(ctx, cmd)
179+
return cmd
180+
}
181+
182+
// `VLINKS key element WITHSCORES`
183+
func (c cmdable) VLinksWithScores(ctx context.Context, key, element string) *MapStringFloatCmd {
184+
cmd := NewMapStringFloatCmd(ctx, "vlinks", key, element, "withscores")
185+
_ = c(ctx, cmd)
186+
return cmd
187+
}
188+
189+
// `VRANDMEMBER key`
190+
func (c cmdable) VRandMember(ctx context.Context, key string) *StringCmd {
191+
cmd := NewStringCmd(ctx, "vrandmember", key)
192+
_ = c(ctx, cmd)
193+
return cmd
194+
}
195+
196+
// `VRANDMEMBER key [count]`
197+
func (c cmdable) VRandMemberCount(ctx context.Context, key string, count int) *StringSliceCmd {
198+
cmd := NewStringSliceCmd(ctx, "vrandmember", key, count)
199+
_ = c(ctx, cmd)
200+
return cmd
201+
}
202+
203+
// `VREM key element`
204+
func (c cmdable) VRem(ctx context.Context, key, element string) *BoolCmd {
205+
cmd := NewBoolCmd(ctx, "vrem", key, element)
206+
_ = c(ctx, cmd)
207+
return cmd
208+
}
209+
210+
// `VSETATTR key element "{ JSON obj }"`
211+
func (c cmdable) VSetAttr(ctx context.Context, key, element, attr string) *BoolCmd {
212+
cmd := NewBoolCmd(ctx, "vsetattr", key, element, attr)
213+
_ = c(ctx, cmd)
214+
return cmd
215+
}
216+
217+
// `VSIM key (ELE | FP32 | VALUES num) (vector | element)`
218+
func (c cmdable) VSim(ctx context.Context, key string, val Vector) *StringSliceCmd {
219+
return c.VSimArgs(ctx, key, val, VSimArgs{})
220+
}
221+
222+
// `VSIM key (ELE | FP32 | VALUES num) (vector | element) WITHSCORES`
223+
func (c cmdable) VSimWithScores(ctx context.Context, key string, val Vector) *MapStringFloatCmd {
224+
return c.VSimArgsWithScores(ctx, key, val, VSimArgs{})
225+
}
226+
227+
type VSimArgs struct {
228+
Count int64
229+
EF int64
230+
Filter string
231+
FilterEF int64
232+
Truth bool
233+
NoThread bool
234+
// The `VSim` command in Redis has the option, by the doc in Redis.io don't have.
235+
// Epsilon float64
236+
}
237+
238+
func (v VSimArgs) appendArgs(args []any) []any {
239+
if v.Count > 0 {
240+
args = append(args, "count", v.Count)
241+
}
242+
if v.EF > 0 {
243+
args = append(args, "ef", v.EF)
244+
}
245+
if len(v.Filter) > 0 {
246+
args = append(args, "filter", v.Filter)
247+
}
248+
if v.FilterEF > 0 {
249+
args = append(args, "filter-ef", v.FilterEF)
250+
}
251+
if v.Truth {
252+
args = append(args, "truth")
253+
}
254+
if v.NoThread {
255+
args = append(args, "nothread")
256+
}
257+
// if v.Epsilon > 0 {
258+
// args = append(args, "Epsilon", v.Epsilon)
259+
// }
260+
return args
261+
}
262+
263+
// `VSIM key (ELE | FP32 | VALUES num) (vector | element) [COUNT num]
264+
// [EF search-exploration-factor] [FILTER expression] [FILTER-EF max-filtering-effort] [TRUTH] [NOTHREAD]`
265+
func (c cmdable) VSimArgs(ctx context.Context, key string, val Vector, simArgs VSimArgs) *StringSliceCmd {
266+
args := []any{"vsim", key}
267+
args = append(args, val.Value()...)
268+
args = simArgs.appendArgs(args)
269+
cmd := NewStringSliceCmd(ctx, args...)
270+
_ = c(ctx, cmd)
271+
return cmd
272+
}
273+
274+
// `VSIM key (ELE | FP32 | VALUES num) (vector | element) [WITHSCORES] [COUNT num]
275+
// [EF search-exploration-factor] [FILTER expression] [FILTER-EF max-filtering-effort] [TRUTH] [NOTHREAD]`
276+
func (c cmdable) VSimArgsWithScores(ctx context.Context, key string, val Vector, simArgs VSimArgs) *MapStringFloatCmd {
277+
args := []any{"vsim", key}
278+
args = append(args, val.Value()...)
279+
args = append(args, "withscores")
280+
args = simArgs.appendArgs(args)
281+
cmd := NewMapStringFloatCmd(ctx, args...)
282+
_ = c(ctx, cmd)
283+
return cmd
284+
}

0 commit comments

Comments
 (0)