1
+ // EXAMPLE: query_combined
2
+ // HIDE_START
3
+ import assert from 'node:assert' ;
4
+ import fs from 'node:fs' ;
5
+ import { createClient } from 'redis' ;
6
+ import { SchemaFieldTypes , VectorAlgorithms } from '@redis/search' ;
7
+ import { pipeline } from '@xenova/transformers' ;
8
+
9
+ function float32Buffer ( arr ) {
10
+ const floatArray = new Float32Array ( arr ) ;
11
+ const float32Buffer = Buffer . from ( floatArray . buffer ) ;
12
+ return float32Buffer ;
13
+ }
14
+
15
+ async function embedText ( sentence ) {
16
+ let modelName = 'Xenova/all-MiniLM-L6-v2' ;
17
+ let pipe = await pipeline ( 'feature-extraction' , modelName ) ;
18
+
19
+ let vectorOutput = await pipe ( sentence , {
20
+ pooling : 'mean' ,
21
+ normalize : true ,
22
+ } ) ;
23
+
24
+ if ( vectorOutput == null ) {
25
+ throw new Error ( 'vectorOutput is undefined' ) ;
26
+ }
27
+
28
+ const embedding = Object . values ( vectorOutput . data ) ;
29
+
30
+ return embedding ;
31
+ }
32
+
33
+ let query = 'Bike for small kids' ;
34
+ let vector_query = float32Buffer ( await embedText ( 'That is a very happy person' ) ) ;
35
+
36
+ const client = createClient ( ) ;
37
+ await client . connect ( ) . catch ( console . error ) ;
38
+
39
+ // create index
40
+ await client . ft . create ( 'idx:bicycle' , {
41
+ '$.description' : {
42
+ type : SchemaFieldTypes . TEXT ,
43
+ AS : 'description'
44
+ } ,
45
+ '$.condition' : {
46
+ type : SchemaFieldTypes . TAG ,
47
+ AS : 'condition'
48
+ } ,
49
+ '$.price' : {
50
+ type : SchemaFieldTypes . NUMERIC ,
51
+ AS : 'price'
52
+ } ,
53
+ '$.description_embeddings' : {
54
+ type : SchemaFieldTypes . VECTOR ,
55
+ TYPE : 'FLOAT32' ,
56
+ ALGORITHM : VectorAlgorithms . FLAT ,
57
+ DIM : 384 ,
58
+ DISTANCE_METRIC : 'COSINE' ,
59
+ AS : 'vector' ,
60
+ }
61
+ } , {
62
+ ON : 'JSON' ,
63
+ PREFIX : 'bicycle:'
64
+ } ) ;
65
+
66
+ // load data
67
+ const bicycles = JSON . parse ( fs . readFileSync ( 'data/query_vector.json' , 'utf8' ) ) ;
68
+
69
+ await Promise . all (
70
+ bicycles . map ( ( bicycle , bid ) => {
71
+ return client . json . set ( `bicycle:${ bid } ` , '$' , bicycle ) ;
72
+ } )
73
+ ) ;
74
+ // HIDE_END
75
+
76
+ // STEP_START combined1
77
+ const res1 = await client . ft . search ( 'idx:bicycle' , '@price:[500 1000] @condition:{new}' ) ;
78
+ console . log ( res1 . total ) ; // >>> 1
79
+ console . log ( res1 ) ; // >>>
80
+ //{
81
+ // total: 1,
82
+ // documents: [ { id: 'bicycle:5', value: [Object: null prototype] } ]
83
+ //}
84
+ // REMOVE_START
85
+ assert . strictEqual ( res1 . total , 1 ) ;
86
+ // REMOVE_END
87
+ // STEP_END
88
+
89
+ // STEP_START combined2
90
+ const res2 = await client . ft . search ( 'idx:bicycle' , 'kids @price:[500 1000] @condition:{used}' ) ;
91
+ console . log ( res2 . total ) ; // >>> 1
92
+ console . log ( res2 ) ; // >>>
93
+ // {
94
+ // total: 1,
95
+ // documents: [ { id: 'bicycle:2', value: [Object: null prototype] } ]
96
+ // }
97
+ // REMOVE_START
98
+ assert . strictEqual ( res2 . total , 1 ) ;
99
+ // REMOVE_END
100
+ // STEP_END
101
+
102
+ // STEP_START combined3
103
+ const res3 = await client . ft . search ( 'idx:bicycle' , '(kids | small) @condition:{used}' ) ;
104
+ console . log ( res3 . total ) ; // >>> 2
105
+ console . log ( res3 ) ; // >>>
106
+ //{
107
+ // total: 2,
108
+ // documents: [
109
+ // { id: 'bicycle:2', value: [Object: null prototype] },
110
+ // { id: 'bicycle:1', value: [Object: null prototype] }
111
+ // ]
112
+ //}
113
+ // REMOVE_START
114
+ assert . strictEqual ( res3 . total , 2 ) ;
115
+ // REMOVE_END
116
+ // STEP_END
117
+
118
+ // STEP_START combined4
119
+ const res4 = await client . ft . search ( 'idx:bicycle' , '@description:(kids | small) @condition:{used}' ) ;
120
+ console . log ( res4 . total ) ; // >>> 2
121
+ console . log ( res4 ) ; // >>>
122
+ //{
123
+ // total: 2,
124
+ // documents: [
125
+ // { id: 'bicycle:2', value: [Object: null prototype] },
126
+ // { id: 'bicycle:1', value: [Object: null prototype] }
127
+ // ]
128
+ //}
129
+ // REMOVE_START
130
+ assert . strictEqual ( res4 . total , 2 ) ;
131
+ // REMOVE_END
132
+ // STEP_END
133
+
134
+ // STEP_START combined5
135
+ const res5 = await client . ft . search ( 'idx:bicycle' , '@description:(kids | small) @condition:{new | used}' ) ;
136
+ console . log ( res5 . total ) ; // >>> 3
137
+ console . log ( res5 ) ; // >>>
138
+ //{
139
+ // total: 3,
140
+ // documents: [
141
+ // { id: 'bicycle:1', value: [Object: null prototype] },
142
+ // { id: 'bicycle:0', value: [Object: null prototype] },
143
+ // { id: 'bicycle:2', value: [Object: null prototype] }
144
+ // ]
145
+ //}
146
+ // REMOVE_START
147
+ assert . strictEqual ( res5 . total , 3 ) ;
148
+ // REMOVE_END
149
+ // STEP_END
150
+
151
+ // STEP_START combined6
152
+ const res6 = await client . ft . search ( 'idx:bicycle' , '@price:[500 1000] -@condition:{new}' ) ;
153
+ console . log ( res6 . total ) ; // >>> 2
154
+ console . log ( res6 ) ; // >>>
155
+ //{
156
+ // total: 2,
157
+ // documents: [
158
+ // { id: 'bicycle:2', value: [Object: null prototype] },
159
+ // { id: 'bicycle:9', value: [Object: null prototype] }
160
+ // ]
161
+ //}
162
+ // REMOVE_START
163
+ assert . strictEqual ( res6 . total , 2 ) ;
164
+ // REMOVE_END
165
+ // STEP_END
166
+
167
+ // STEP_START combined7
168
+ const res7 = await client . ft . search ( 'idx:bicycle' ,
169
+ '(@price:[500 1000] -@condition:{new})=>[KNN 3 @vector $query_vector]' , {
170
+ PARAMS : { query_vector : vector_query } ,
171
+ DIALECT : 2
172
+ }
173
+ ) ;
174
+ console . log ( res7 . total ) ; // >>> 2
175
+ console . log ( res7 ) ; // >>>
176
+ //{
177
+ // total: 2,
178
+ // documents: [
179
+ // { id: 'bicycle:2', value: [Object: null prototype] },
180
+ // { id: 'bicycle:9', value: [Object: null prototype] }
181
+ // ]
182
+ //}
183
+ // REMOVE_START
184
+ assert . strictEqual ( res7 . total , 2 ) ;
185
+ // REMOVE_END
186
+ // STEP_END
187
+
188
+ // REMOVE_START
189
+ // destroy index and data
190
+ await client . ft . dropIndex ( 'idx:bicycle' , { DD : true } ) ;
191
+ await client . disconnect ( ) ;
192
+ // REMOVE_END
0 commit comments