zvec-ruby 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +21 -0
- data/LICENSE +190 -0
- data/README.md +189 -0
- data/Rakefile +83 -0
- data/examples/basic.rb +63 -0
- data/examples/with_ruby_llm.rb +79 -0
- data/ext/zvec/extconf.rb +100 -0
- data/ext/zvec/zvec_ext.cpp +771 -0
- data/lib/zvec/active_record.rb +113 -0
- data/lib/zvec/collection.rb +165 -0
- data/lib/zvec/data_types.rb +63 -0
- data/lib/zvec/doc.rb +107 -0
- data/lib/zvec/query.rb +28 -0
- data/lib/zvec/ruby_llm.rb +108 -0
- data/lib/zvec/schema.rb +70 -0
- data/lib/zvec/version.rb +3 -0
- data/lib/zvec.rb +22 -0
- data/test/test_active_record.rb +55 -0
- data/test/test_collection.rb +312 -0
- data/test/test_data_types.rb +165 -0
- data/test/test_doc.rb +271 -0
- data/test/test_ext_bindings.rb +313 -0
- data/test/test_helper.rb +170 -0
- data/test/test_query.rb +64 -0
- data/test/test_ruby_llm_store.rb +166 -0
- data/test/test_schema.rb +133 -0
- data/test/test_version.rb +19 -0
- data/zvec.gemspec +43 -0
- metadata +129 -0
data/test/test_doc.rb
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
require_relative "test_helper"
|
|
2
|
+
|
|
3
|
+
class TestDoc < Minitest::Test
|
|
4
|
+
def setup
|
|
5
|
+
@schema = Zvec::Schema.new("test") do
|
|
6
|
+
string "title"
|
|
7
|
+
int32 "count"
|
|
8
|
+
float "score"
|
|
9
|
+
double "precise"
|
|
10
|
+
bool "active"
|
|
11
|
+
vector "embedding", dimension: 4
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# --- Initialization ---
|
|
16
|
+
|
|
17
|
+
def test_initialize_default
|
|
18
|
+
doc = Zvec::Doc.new
|
|
19
|
+
assert_equal "", doc.pk
|
|
20
|
+
assert_equal 0.0, doc.score
|
|
21
|
+
assert doc.empty?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def test_initialize_with_pk
|
|
25
|
+
doc = Zvec::Doc.new(pk: "abc")
|
|
26
|
+
assert_equal "abc", doc.pk
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def test_initialize_with_integer_pk
|
|
30
|
+
doc = Zvec::Doc.new(pk: 42)
|
|
31
|
+
assert_equal "42", doc.pk
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def test_initialize_with_fields_and_schema
|
|
35
|
+
doc = Zvec::Doc.new(pk: "d1", fields: { "title" => "Hello" }, schema: @schema)
|
|
36
|
+
assert_equal "Hello", doc["title"]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# --- pk ---
|
|
40
|
+
|
|
41
|
+
def test_pk_setter
|
|
42
|
+
doc = Zvec::Doc.new
|
|
43
|
+
doc.pk = "new_pk"
|
|
44
|
+
assert_equal "new_pk", doc.pk
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def test_pk_setter_converts_to_string
|
|
48
|
+
doc = Zvec::Doc.new
|
|
49
|
+
doc.pk = 123
|
|
50
|
+
assert_equal "123", doc.pk
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# --- String fields ---
|
|
54
|
+
|
|
55
|
+
def test_set_and_get_string
|
|
56
|
+
doc = Zvec::Doc.new(schema: @schema)
|
|
57
|
+
doc["title"] = "Hello World"
|
|
58
|
+
assert_equal "Hello World", doc["title"]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def test_set_string_without_schema_auto_detects
|
|
62
|
+
doc = Zvec::Doc.new
|
|
63
|
+
doc["name"] = "auto"
|
|
64
|
+
assert_equal "auto", doc["name"]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# --- Integer fields ---
|
|
68
|
+
|
|
69
|
+
def test_set_and_get_int32
|
|
70
|
+
doc = Zvec::Doc.new(schema: @schema)
|
|
71
|
+
doc["count"] = 42
|
|
72
|
+
assert_equal 42, doc["count"]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def test_set_integer_without_schema_uses_int64
|
|
76
|
+
doc = Zvec::Doc.new
|
|
77
|
+
doc["num"] = 99
|
|
78
|
+
assert_equal 99, doc["num"]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# --- Float fields ---
|
|
82
|
+
|
|
83
|
+
def test_set_and_get_float
|
|
84
|
+
doc = Zvec::Doc.new(schema: @schema)
|
|
85
|
+
doc["score"] = 3.14
|
|
86
|
+
val = doc["score"]
|
|
87
|
+
assert_in_delta 3.14, val, 0.01
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def test_set_and_get_double
|
|
91
|
+
doc = Zvec::Doc.new(schema: @schema)
|
|
92
|
+
doc["precise"] = 2.718281828
|
|
93
|
+
val = doc["precise"]
|
|
94
|
+
assert_in_delta 2.718281828, val, 0.0001
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def test_set_float_without_schema_auto_detects
|
|
98
|
+
doc = Zvec::Doc.new
|
|
99
|
+
doc["val"] = 1.5
|
|
100
|
+
assert_in_delta 1.5, doc["val"], 0.01
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# --- Bool fields ---
|
|
104
|
+
|
|
105
|
+
def test_set_and_get_bool_true
|
|
106
|
+
doc = Zvec::Doc.new(schema: @schema)
|
|
107
|
+
doc["active"] = true
|
|
108
|
+
assert_equal true, doc["active"]
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def test_set_and_get_bool_false
|
|
112
|
+
doc = Zvec::Doc.new(schema: @schema)
|
|
113
|
+
doc["active"] = false
|
|
114
|
+
assert_equal false, doc["active"]
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def test_set_bool_without_schema_auto_detects
|
|
118
|
+
doc = Zvec::Doc.new
|
|
119
|
+
doc["flag"] = true
|
|
120
|
+
assert_equal true, doc["flag"]
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# --- Vector fields ---
|
|
124
|
+
|
|
125
|
+
def test_set_and_get_float_vector
|
|
126
|
+
doc = Zvec::Doc.new(schema: @schema)
|
|
127
|
+
vec = [1.0, 2.0, 3.0, 4.0]
|
|
128
|
+
doc["embedding"] = vec
|
|
129
|
+
result = doc["embedding"]
|
|
130
|
+
assert_kind_of Array, result
|
|
131
|
+
assert_equal 4, result.size
|
|
132
|
+
assert_in_delta 1.0, result[0], 0.001
|
|
133
|
+
assert_in_delta 4.0, result[3], 0.001
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def test_set_array_of_integers_as_vector
|
|
137
|
+
doc = Zvec::Doc.new
|
|
138
|
+
doc["vec"] = [1, 2, 3]
|
|
139
|
+
result = doc["vec"]
|
|
140
|
+
assert_kind_of Array, result
|
|
141
|
+
assert_in_delta 1.0, result[0], 0.01
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# --- String array fields ---
|
|
145
|
+
|
|
146
|
+
def test_set_and_get_string_array
|
|
147
|
+
doc = Zvec::Doc.new
|
|
148
|
+
doc["tags"] = ["ruby", "vector", "db"]
|
|
149
|
+
result = doc["tags"]
|
|
150
|
+
assert_kind_of Array, result
|
|
151
|
+
assert_equal ["ruby", "vector", "db"], result
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# --- Null handling ---
|
|
155
|
+
|
|
156
|
+
def test_set_nil_value
|
|
157
|
+
doc = Zvec::Doc.new
|
|
158
|
+
doc["title"] = "Hello"
|
|
159
|
+
doc["title"] = nil
|
|
160
|
+
assert_nil doc["title"]
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# --- Missing fields ---
|
|
164
|
+
|
|
165
|
+
def test_get_missing_field_returns_nil
|
|
166
|
+
doc = Zvec::Doc.new
|
|
167
|
+
assert_nil doc["nonexistent"]
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# --- field_names ---
|
|
171
|
+
|
|
172
|
+
def test_field_names
|
|
173
|
+
doc = Zvec::Doc.new(schema: @schema)
|
|
174
|
+
doc["title"] = "Hello"
|
|
175
|
+
doc["count"] = 1
|
|
176
|
+
names = doc.field_names
|
|
177
|
+
assert_includes names, "title"
|
|
178
|
+
assert_includes names, "count"
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# --- empty? ---
|
|
182
|
+
|
|
183
|
+
def test_empty_initially
|
|
184
|
+
doc = Zvec::Doc.new
|
|
185
|
+
assert doc.empty?
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def test_not_empty_after_set
|
|
189
|
+
doc = Zvec::Doc.new
|
|
190
|
+
doc["x"] = "y"
|
|
191
|
+
refute doc.empty?
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# --- to_h ---
|
|
195
|
+
|
|
196
|
+
def test_to_h
|
|
197
|
+
doc = Zvec::Doc.new(pk: "pk1")
|
|
198
|
+
doc["title"] = "Hi"
|
|
199
|
+
h = doc.to_h
|
|
200
|
+
assert_kind_of Hash, h
|
|
201
|
+
assert_equal "pk1", h["pk"]
|
|
202
|
+
assert_equal 0.0, h["score"]
|
|
203
|
+
assert_equal "Hi", h["title"]
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def test_to_h_includes_all_fields
|
|
207
|
+
doc = Zvec::Doc.new(pk: "x")
|
|
208
|
+
doc["a"] = "one"
|
|
209
|
+
doc["b"] = "two"
|
|
210
|
+
h = doc.to_h
|
|
211
|
+
assert_equal "one", h["a"]
|
|
212
|
+
assert_equal "two", h["b"]
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# --- to_s ---
|
|
216
|
+
|
|
217
|
+
def test_to_s_returns_string
|
|
218
|
+
doc = Zvec::Doc.new(pk: "test")
|
|
219
|
+
assert_kind_of String, doc.to_s
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# --- bracket accessor ---
|
|
223
|
+
|
|
224
|
+
def test_bracket_set_and_get
|
|
225
|
+
doc = Zvec::Doc.new
|
|
226
|
+
doc["key"] = "value"
|
|
227
|
+
assert_equal "value", doc["key"]
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# --- from_ext ---
|
|
231
|
+
|
|
232
|
+
def test_from_ext
|
|
233
|
+
ext_doc = Zvec::Ext::Doc.new
|
|
234
|
+
ext_doc.pk = "wrapped"
|
|
235
|
+
doc = Zvec::Doc.from_ext(ext_doc, schema: @schema)
|
|
236
|
+
assert_equal "wrapped", doc.pk
|
|
237
|
+
assert_same ext_doc, doc.ext_doc
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def test_from_ext_without_schema
|
|
241
|
+
ext_doc = Zvec::Ext::Doc.new
|
|
242
|
+
doc = Zvec::Doc.from_ext(ext_doc)
|
|
243
|
+
assert_equal ext_doc, doc.ext_doc
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
# --- symbol keys ---
|
|
247
|
+
|
|
248
|
+
def test_symbol_field_name_set
|
|
249
|
+
doc = Zvec::Doc.new
|
|
250
|
+
doc.set(:sym_field, "value")
|
|
251
|
+
assert_equal "value", doc["sym_field"]
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def test_symbol_field_name_get
|
|
255
|
+
doc = Zvec::Doc.new
|
|
256
|
+
doc["sym_field"] = "value"
|
|
257
|
+
assert_equal "value", doc.get(:sym_field)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# --- empty array ---
|
|
261
|
+
|
|
262
|
+
def test_set_empty_array_as_vector
|
|
263
|
+
doc = Zvec::Doc.new
|
|
264
|
+
doc["empty"] = []
|
|
265
|
+
# Empty arrays treated as float vectors (empty)
|
|
266
|
+
result = doc["empty"]
|
|
267
|
+
# Depending on implementation, may be nil or empty array
|
|
268
|
+
# Just verify it doesn't crash
|
|
269
|
+
assert(result.nil? || result == [])
|
|
270
|
+
end
|
|
271
|
+
end
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
require_relative "test_helper"
|
|
2
|
+
|
|
3
|
+
# Tests for low-level C++ extension bindings.
|
|
4
|
+
# Skipped when native ext is not available.
|
|
5
|
+
class TestExtBindings < Minitest::Test
|
|
6
|
+
def setup
|
|
7
|
+
skip "Native extension not available" unless NATIVE_EXT_AVAILABLE
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# --- Enums ---
|
|
11
|
+
|
|
12
|
+
def test_data_type_enum
|
|
13
|
+
assert_respond_to Zvec::Ext::DataType::STRING, :to_s
|
|
14
|
+
refute_equal Zvec::Ext::DataType::STRING, Zvec::Ext::DataType::INT32
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def test_index_type_enum
|
|
18
|
+
refute_nil Zvec::Ext::IndexType::HNSW
|
|
19
|
+
refute_nil Zvec::Ext::IndexType::FLAT
|
|
20
|
+
refute_nil Zvec::Ext::IndexType::IVF
|
|
21
|
+
refute_nil Zvec::Ext::IndexType::INVERT
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def test_metric_type_enum
|
|
25
|
+
refute_nil Zvec::Ext::MetricType::L2
|
|
26
|
+
refute_nil Zvec::Ext::MetricType::IP
|
|
27
|
+
refute_nil Zvec::Ext::MetricType::COSINE
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_quantize_type_enum
|
|
31
|
+
refute_nil Zvec::Ext::QuantizeType::FP16
|
|
32
|
+
refute_nil Zvec::Ext::QuantizeType::INT8
|
|
33
|
+
refute_nil Zvec::Ext::QuantizeType::INT4
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# --- CollectionOptions ---
|
|
37
|
+
|
|
38
|
+
def test_collection_options_defaults
|
|
39
|
+
opts = Zvec::Ext::CollectionOptions.new
|
|
40
|
+
refute opts.read_only?
|
|
41
|
+
assert opts.enable_mmap?
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def test_collection_options_setters
|
|
45
|
+
opts = Zvec::Ext::CollectionOptions.new
|
|
46
|
+
opts.read_only = true
|
|
47
|
+
opts.enable_mmap = false
|
|
48
|
+
opts.max_buffer_size = 1024
|
|
49
|
+
assert opts.read_only?
|
|
50
|
+
refute opts.enable_mmap?
|
|
51
|
+
assert_equal 1024, opts.max_buffer_size
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# --- FieldSchema ---
|
|
55
|
+
|
|
56
|
+
def test_field_schema_basic
|
|
57
|
+
fs = Zvec::Ext::FieldSchema.new("title", Zvec::Ext::DataType::STRING)
|
|
58
|
+
assert_equal "title", fs.name
|
|
59
|
+
assert_equal Zvec::Ext::DataType::STRING, fs.data_type
|
|
60
|
+
refute fs.nullable?
|
|
61
|
+
assert_equal 0, fs.dimension
|
|
62
|
+
refute fs.vector_field?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def test_field_schema_vector
|
|
66
|
+
fs = Zvec::Ext::FieldSchema.new("vec", Zvec::Ext::DataType::VECTOR_FP32)
|
|
67
|
+
fs.dimension = 128
|
|
68
|
+
assert fs.vector_field?
|
|
69
|
+
assert_equal 128, fs.dimension
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def test_field_schema_nullable
|
|
73
|
+
fs = Zvec::Ext::FieldSchema.new("opt", Zvec::Ext::DataType::STRING)
|
|
74
|
+
fs.nullable = true
|
|
75
|
+
assert fs.nullable?
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def test_field_schema_to_s
|
|
79
|
+
fs = Zvec::Ext::FieldSchema.new("x", Zvec::Ext::DataType::INT32)
|
|
80
|
+
assert_kind_of String, fs.to_s
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# --- CollectionSchema ---
|
|
84
|
+
|
|
85
|
+
def test_collection_schema_basic
|
|
86
|
+
cs = Zvec::Ext::CollectionSchema.new("test")
|
|
87
|
+
assert_equal "test", cs.name
|
|
88
|
+
assert_equal [], cs.field_names
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def test_collection_schema_add_field
|
|
92
|
+
cs = Zvec::Ext::CollectionSchema.new("test")
|
|
93
|
+
fs = Zvec::Ext::FieldSchema.new("title", Zvec::Ext::DataType::STRING)
|
|
94
|
+
cs.add_field(fs)
|
|
95
|
+
assert cs.has_field?("title")
|
|
96
|
+
assert_includes cs.field_names, "title"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def test_collection_schema_vector_fields
|
|
100
|
+
cs = Zvec::Ext::CollectionSchema.new("test")
|
|
101
|
+
cs.add_field(Zvec::Ext::FieldSchema.new("title", Zvec::Ext::DataType::STRING))
|
|
102
|
+
vf = Zvec::Ext::FieldSchema.new("vec", Zvec::Ext::DataType::VECTOR_FP32)
|
|
103
|
+
vf.dimension = 4
|
|
104
|
+
cs.add_field(vf)
|
|
105
|
+
|
|
106
|
+
vec_fields = cs.vector_fields
|
|
107
|
+
assert_equal 1, vec_fields.size
|
|
108
|
+
assert_equal "vec", vec_fields.first.name
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def test_collection_schema_forward_fields
|
|
112
|
+
cs = Zvec::Ext::CollectionSchema.new("test")
|
|
113
|
+
cs.add_field(Zvec::Ext::FieldSchema.new("title", Zvec::Ext::DataType::STRING))
|
|
114
|
+
vf = Zvec::Ext::FieldSchema.new("vec", Zvec::Ext::DataType::VECTOR_FP32)
|
|
115
|
+
vf.dimension = 4
|
|
116
|
+
cs.add_field(vf)
|
|
117
|
+
|
|
118
|
+
fwd = cs.forward_fields
|
|
119
|
+
assert_equal 1, fwd.size
|
|
120
|
+
assert_equal "title", fwd.first.name
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# --- Doc ---
|
|
124
|
+
|
|
125
|
+
def test_doc_basic
|
|
126
|
+
d = Zvec::Ext::Doc.new
|
|
127
|
+
assert_equal "", d.pk
|
|
128
|
+
assert_equal 0.0, d.score
|
|
129
|
+
assert d.empty?
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def test_doc_pk
|
|
133
|
+
d = Zvec::Ext::Doc.new
|
|
134
|
+
d.pk = "hello"
|
|
135
|
+
assert_equal "hello", d.pk
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def test_doc_score
|
|
139
|
+
d = Zvec::Ext::Doc.new
|
|
140
|
+
d.score = 0.95
|
|
141
|
+
assert_in_delta 0.95, d.score, 0.001
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def test_doc_string_field
|
|
145
|
+
d = Zvec::Ext::Doc.new
|
|
146
|
+
d.set_string("name", "Alice")
|
|
147
|
+
assert d.has?("name")
|
|
148
|
+
assert d.has_value?("name")
|
|
149
|
+
assert_equal "Alice", d.get_string("name")
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def test_doc_bool_field
|
|
153
|
+
d = Zvec::Ext::Doc.new
|
|
154
|
+
d.set_bool("active", true)
|
|
155
|
+
assert_equal true, d.get_bool("active")
|
|
156
|
+
d.set_bool("active", false)
|
|
157
|
+
assert_equal false, d.get_bool("active")
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def test_doc_int32_field
|
|
161
|
+
d = Zvec::Ext::Doc.new
|
|
162
|
+
d.set_int32("count", 42)
|
|
163
|
+
assert_equal 42, d.get_int32("count")
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def test_doc_int64_field
|
|
167
|
+
d = Zvec::Ext::Doc.new
|
|
168
|
+
d.set_int64("big", 9_999_999_999)
|
|
169
|
+
assert_equal 9_999_999_999, d.get_int64("big")
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def test_doc_float_field
|
|
173
|
+
d = Zvec::Ext::Doc.new
|
|
174
|
+
d.set_float("val", 3.14)
|
|
175
|
+
assert_in_delta 3.14, d.get_float("val"), 0.01
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def test_doc_double_field
|
|
179
|
+
d = Zvec::Ext::Doc.new
|
|
180
|
+
d.set_double("precise", 2.718281828)
|
|
181
|
+
assert_in_delta 2.718281828, d.get_double("precise"), 0.0001
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def test_doc_float_vector_field
|
|
185
|
+
d = Zvec::Ext::Doc.new
|
|
186
|
+
d.set_float_vector("vec", [1.0, 2.0, 3.0])
|
|
187
|
+
result = d.get_float_vector("vec")
|
|
188
|
+
assert_kind_of Array, result
|
|
189
|
+
assert_equal 3, result.size
|
|
190
|
+
assert_in_delta 1.0, result[0], 0.001
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def test_doc_string_array_field
|
|
194
|
+
d = Zvec::Ext::Doc.new
|
|
195
|
+
d.set_string_array("tags", ["a", "b", "c"])
|
|
196
|
+
result = d.get_string_array("tags")
|
|
197
|
+
assert_equal ["a", "b", "c"], result
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def test_doc_null_field
|
|
201
|
+
d = Zvec::Ext::Doc.new
|
|
202
|
+
d.set_null("empty")
|
|
203
|
+
assert d.has?("empty")
|
|
204
|
+
refute d.has_value?("empty")
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def test_doc_field_names
|
|
208
|
+
d = Zvec::Ext::Doc.new
|
|
209
|
+
d.set_string("a", "x")
|
|
210
|
+
d.set_int32("b", 1)
|
|
211
|
+
names = d.field_names
|
|
212
|
+
assert_includes names, "a"
|
|
213
|
+
assert_includes names, "b"
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def test_doc_get_missing_returns_nil
|
|
217
|
+
d = Zvec::Ext::Doc.new
|
|
218
|
+
assert_nil d.get_string("nope")
|
|
219
|
+
assert_nil d.get_int32("nope")
|
|
220
|
+
assert_nil d.get_float("nope")
|
|
221
|
+
assert_nil d.get_float_vector("nope")
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def test_doc_type_mismatch_returns_nil
|
|
225
|
+
d = Zvec::Ext::Doc.new
|
|
226
|
+
d.set_string("x", "hello")
|
|
227
|
+
assert_nil d.get_int32("x")
|
|
228
|
+
assert_nil d.get_float("x")
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def test_doc_to_s
|
|
232
|
+
d = Zvec::Ext::Doc.new
|
|
233
|
+
d.pk = "test"
|
|
234
|
+
assert_kind_of String, d.to_s
|
|
235
|
+
assert_includes d.to_s, "test"
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# --- VectorQuery ---
|
|
239
|
+
|
|
240
|
+
def test_vector_query_basic
|
|
241
|
+
q = Zvec::Ext::VectorQuery.new
|
|
242
|
+
q.field_name = "vec"
|
|
243
|
+
q.topk = 5
|
|
244
|
+
assert_equal "vec", q.field_name
|
|
245
|
+
assert_equal 5, q.topk
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def test_vector_query_filter
|
|
249
|
+
q = Zvec::Ext::VectorQuery.new
|
|
250
|
+
q.filter = "x > 1"
|
|
251
|
+
assert_equal "x > 1", q.filter
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def test_vector_query_include_vector
|
|
255
|
+
q = Zvec::Ext::VectorQuery.new
|
|
256
|
+
q.include_vector = true
|
|
257
|
+
assert q.include_vector?
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# --- Index params ---
|
|
261
|
+
|
|
262
|
+
def test_hnsw_index_params
|
|
263
|
+
p = Zvec::Ext::HnswIndexParams.new(Zvec::Ext::MetricType::COSINE)
|
|
264
|
+
assert_equal 16, p.m
|
|
265
|
+
assert_equal 200, p.ef_construction
|
|
266
|
+
assert_equal Zvec::Ext::MetricType::COSINE, p.metric_type
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def test_hnsw_index_params_custom
|
|
270
|
+
p = Zvec::Ext::HnswIndexParams.new(Zvec::Ext::MetricType::L2, 32, 400)
|
|
271
|
+
assert_equal 32, p.m
|
|
272
|
+
assert_equal 400, p.ef_construction
|
|
273
|
+
assert_equal Zvec::Ext::MetricType::L2, p.metric_type
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def test_flat_index_params
|
|
277
|
+
p = Zvec::Ext::FlatIndexParams.new(Zvec::Ext::MetricType::IP)
|
|
278
|
+
assert_equal Zvec::Ext::MetricType::IP, p.metric_type
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def test_ivf_index_params
|
|
282
|
+
p = Zvec::Ext::IVFIndexParams.new(Zvec::Ext::MetricType::L2, 512, 20)
|
|
283
|
+
assert_equal 512, p.n_list
|
|
284
|
+
assert_equal 20, p.n_iters
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def test_invert_index_params
|
|
288
|
+
p = Zvec::Ext::InvertIndexParams.new
|
|
289
|
+
assert_kind_of Zvec::Ext::InvertIndexParams, p
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
# --- Query params ---
|
|
293
|
+
|
|
294
|
+
def test_hnsw_query_params
|
|
295
|
+
p = Zvec::Ext::HnswQueryParams.new(300)
|
|
296
|
+
assert_equal 300, p.ef
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def test_hnsw_query_params_default
|
|
300
|
+
p = Zvec::Ext::HnswQueryParams.new
|
|
301
|
+
assert_equal 200, p.ef
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def test_ivf_query_params
|
|
305
|
+
p = Zvec::Ext::IVFQueryParams.new(20)
|
|
306
|
+
assert_equal 20, p.nprobe
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def test_flat_query_params
|
|
310
|
+
p = Zvec::Ext::FlatQueryParams.new
|
|
311
|
+
assert_kind_of Zvec::Ext::FlatQueryParams, p
|
|
312
|
+
end
|
|
313
|
+
end
|