1use std::os::raw::c_void;
2
3use crate::error::{check_error, to_cstring, Error, ErrorCode, Result};
4
5pub struct HnswQueryParams {
7 pub(crate) handle: *mut zvec_rust_sys::zvec_hnsw_query_params_t,
8}
9
10impl HnswQueryParams {
11 pub fn new(ef: i32, radius: f32, is_linear: bool, is_using_refiner: bool) -> Self {
13 let handle = unsafe {
14 zvec_rust_sys::zvec_query_params_hnsw_create(ef, radius, is_linear, is_using_refiner)
15 };
16 HnswQueryParams { handle }
17 }
18
19 pub fn set_ef(&mut self, ef: i32) -> Result<()> {
21 check_error(unsafe { zvec_rust_sys::zvec_query_params_hnsw_set_ef(self.handle, ef) })
22 }
23
24 pub fn ef(&self) -> i32 {
26 unsafe { zvec_rust_sys::zvec_query_params_hnsw_get_ef(self.handle) }
27 }
28}
29
30impl Drop for HnswQueryParams {
31 fn drop(&mut self) {
32 if !self.handle.is_null() {
33 unsafe { zvec_rust_sys::zvec_query_params_hnsw_destroy(self.handle) };
34 }
35 }
36}
37
38pub struct IvfQueryParams {
40 pub(crate) handle: *mut zvec_rust_sys::zvec_ivf_query_params_t,
41}
42
43impl IvfQueryParams {
44 pub fn new(nprobe: i32, is_using_refiner: bool, scale_factor: f32) -> Self {
46 let handle = unsafe {
47 zvec_rust_sys::zvec_query_params_ivf_create(nprobe, is_using_refiner, scale_factor)
48 };
49 IvfQueryParams { handle }
50 }
51
52 pub fn set_nprobe(&mut self, nprobe: i32) -> Result<()> {
54 check_error(unsafe { zvec_rust_sys::zvec_query_params_ivf_set_nprobe(self.handle, nprobe) })
55 }
56
57 pub fn nprobe(&self) -> i32 {
59 unsafe { zvec_rust_sys::zvec_query_params_ivf_get_nprobe(self.handle) }
60 }
61}
62
63impl Drop for IvfQueryParams {
64 fn drop(&mut self) {
65 if !self.handle.is_null() {
66 unsafe { zvec_rust_sys::zvec_query_params_ivf_destroy(self.handle) };
67 }
68 }
69}
70
71pub struct FlatQueryParams {
73 pub(crate) handle: *mut zvec_rust_sys::zvec_flat_query_params_t,
74}
75
76impl FlatQueryParams {
77 pub fn new(is_using_refiner: bool, scale_factor: f32) -> Self {
79 let handle =
80 unsafe { zvec_rust_sys::zvec_query_params_flat_create(is_using_refiner, scale_factor) };
81 FlatQueryParams { handle }
82 }
83}
84
85impl Drop for FlatQueryParams {
86 fn drop(&mut self) {
87 if !self.handle.is_null() {
88 unsafe { zvec_rust_sys::zvec_query_params_flat_destroy(self.handle) };
89 }
90 }
91}
92
93pub struct DiskannQueryParams {
95 pub(crate) handle: *mut zvec_rust_sys::zvec_diskann_query_params_t,
96}
97
98impl DiskannQueryParams {
99 pub fn new(list_size: i32) -> Self {
103 let handle = unsafe { zvec_rust_sys::zvec_query_params_diskann_create(list_size) };
104 DiskannQueryParams { handle }
105 }
106
107 pub fn set_list_size(&mut self, list_size: i32) -> Result<()> {
109 check_error(unsafe {
110 zvec_rust_sys::zvec_query_params_diskann_set_list_size(self.handle, list_size)
111 })
112 }
113
114 pub fn list_size(&self) -> i32 {
116 unsafe { zvec_rust_sys::zvec_query_params_diskann_get_list_size(self.handle) }
117 }
118}
119
120impl Drop for DiskannQueryParams {
121 fn drop(&mut self) {
122 if !self.handle.is_null() {
123 unsafe { zvec_rust_sys::zvec_query_params_diskann_destroy(self.handle) };
124 }
125 }
126}
127
128pub struct FtsQueryParams {
130 pub(crate) handle: *mut zvec_rust_sys::zvec_fts_query_params_t,
131}
132
133impl FtsQueryParams {
134 pub fn new(default_operator: Option<&str>) -> Result<Self> {
139 let c_op = default_operator.map(to_cstring).transpose()?;
140 let handle = unsafe {
141 zvec_rust_sys::zvec_query_params_fts_create(
142 c_op.as_ref().map_or(std::ptr::null(), |c| c.as_ptr()),
143 )
144 };
145 if handle.is_null() {
146 return Err(Error {
147 code: ErrorCode::InternalError,
148 message: "failed to create FTS query params".into(),
149 });
150 }
151 Ok(FtsQueryParams { handle })
152 }
153
154 pub fn set_default_operator(&mut self, op: &str) -> Result<()> {
156 let c_op = to_cstring(op)?;
157 check_error(unsafe {
158 zvec_rust_sys::zvec_query_params_fts_set_default_operator(self.handle, c_op.as_ptr())
159 })
160 }
161
162 pub fn default_operator(&self) -> Option<String> {
164 unsafe {
165 let ptr = zvec_rust_sys::zvec_query_params_fts_get_default_operator(self.handle);
166 if ptr.is_null() {
167 return None;
168 }
169 Some(std::ffi::CStr::from_ptr(ptr).to_string_lossy().into_owned())
170 }
171 }
172}
173
174impl Drop for FtsQueryParams {
175 fn drop(&mut self) {
176 if !self.handle.is_null() {
177 unsafe { zvec_rust_sys::zvec_query_params_fts_destroy(self.handle) };
178 }
179 }
180}
181
182pub struct Fts {
187 pub(crate) handle: *mut zvec_rust_sys::zvec_fts_t,
188}
189
190impl Fts {
191 pub fn new() -> Result<Self> {
193 let handle = unsafe { zvec_rust_sys::zvec_fts_create() };
194 if handle.is_null() {
195 return Err(Error {
196 code: ErrorCode::InternalError,
197 message: "failed to create FTS payload".into(),
198 });
199 }
200 Ok(Fts { handle })
201 }
202
203 pub fn set_query_string(&mut self, query: &str) -> Result<()> {
205 let c = to_cstring(query)?;
206 check_error(unsafe { zvec_rust_sys::zvec_fts_set_query_string(self.handle, c.as_ptr()) })
207 }
208
209 pub fn set_match_string(&mut self, match_str: &str) -> Result<()> {
211 let c = to_cstring(match_str)?;
212 check_error(unsafe { zvec_rust_sys::zvec_fts_set_match_string(self.handle, c.as_ptr()) })
213 }
214
215 pub fn query_string(&self) -> Option<String> {
217 unsafe {
218 let ptr = zvec_rust_sys::zvec_fts_get_query_string(self.handle);
219 if ptr.is_null() {
220 return None;
221 }
222 Some(std::ffi::CStr::from_ptr(ptr).to_string_lossy().into_owned())
223 }
224 }
225
226 pub fn match_string(&self) -> Option<String> {
228 unsafe {
229 let ptr = zvec_rust_sys::zvec_fts_get_match_string(self.handle);
230 if ptr.is_null() {
231 return None;
232 }
233 Some(std::ffi::CStr::from_ptr(ptr).to_string_lossy().into_owned())
234 }
235 }
236}
237
238impl Drop for Fts {
239 fn drop(&mut self) {
240 if !self.handle.is_null() {
241 unsafe { zvec_rust_sys::zvec_fts_destroy(self.handle) };
242 }
243 }
244}
245
246pub struct SearchQuery {
248 pub(crate) handle: *mut zvec_rust_sys::zvec_vector_query_t,
249}
250
251impl SearchQuery {
252 pub unsafe fn as_raw(&self) -> *mut zvec_rust_sys::zvec_vector_query_t {
257 self.handle
258 }
259
260 pub unsafe fn from_raw(handle: *mut zvec_rust_sys::zvec_vector_query_t) -> Self {
266 SearchQuery { handle }
267 }
268
269 pub fn new(field_name: &str, vector: &[f32], topk: i32) -> Result<Self> {
271 let handle = unsafe { zvec_rust_sys::zvec_vector_query_create() };
272 if handle.is_null() {
273 return Err(Error {
274 code: ErrorCode::InternalError,
275 message: "failed to create vector query".into(),
276 });
277 }
278
279 let c_field = to_cstring(field_name)?;
280 let query = SearchQuery { handle };
281
282 check_error(unsafe {
283 zvec_rust_sys::zvec_vector_query_set_field_name(query.handle, c_field.as_ptr())
284 })?;
285 check_error(unsafe {
286 zvec_rust_sys::zvec_vector_query_set_query_vector(
287 query.handle,
288 vector.as_ptr() as *const c_void,
289 std::mem::size_of_val(vector),
290 )
291 })?;
292 check_error(unsafe { zvec_rust_sys::zvec_vector_query_set_topk(query.handle, topk) })?;
293
294 Ok(query)
295 }
296
297 pub fn fts(field_name: &str, fts: &Fts, topk: i32) -> Result<Self> {
307 let handle = unsafe { zvec_rust_sys::zvec_vector_query_create() };
308 if handle.is_null() {
309 return Err(Error {
310 code: ErrorCode::InternalError,
311 message: "failed to create vector query".into(),
312 });
313 }
314
315 let mut query = SearchQuery { handle };
317 let c_field = to_cstring(field_name)?;
318
319 check_error(unsafe {
320 zvec_rust_sys::zvec_vector_query_set_field_name(query.handle, c_field.as_ptr())
321 })?;
322 check_error(unsafe { zvec_rust_sys::zvec_vector_query_set_topk(query.handle, topk) })?;
323 query.set_fts(fts)?;
324
325 Ok(query)
326 }
327
328 pub fn builder() -> SearchQueryBuilder {
330 SearchQueryBuilder::new()
331 }
332
333 pub fn set_filter(&mut self, filter: &str) -> Result<()> {
335 let c_filter = to_cstring(filter)?;
336 check_error(unsafe {
337 zvec_rust_sys::zvec_vector_query_set_filter(self.handle, c_filter.as_ptr())
338 })
339 }
340
341 pub fn set_include_vector(&mut self, include: bool) -> Result<()> {
343 check_error(unsafe {
344 zvec_rust_sys::zvec_vector_query_set_include_vector(self.handle, include)
345 })
346 }
347
348 pub fn set_include_doc_id(&mut self, include: bool) -> Result<()> {
350 check_error(unsafe {
351 zvec_rust_sys::zvec_vector_query_set_include_doc_id(self.handle, include)
352 })
353 }
354
355 pub fn set_output_fields(&mut self, fields: &[&str]) -> Result<()> {
357 let c_fields: Vec<_> = fields
358 .iter()
359 .map(|f| to_cstring(f))
360 .collect::<Result<Vec<_>>>()?;
361 let c_ptrs: Vec<_> = c_fields.iter().map(|f| f.as_ptr()).collect();
362 check_error(unsafe {
363 zvec_rust_sys::zvec_vector_query_set_output_fields(
364 self.handle,
365 c_ptrs.as_ptr(),
366 c_ptrs.len(),
367 )
368 })
369 }
370
371 pub fn set_hnsw_params(&mut self, mut params: HnswQueryParams) -> Result<()> {
373 check_error(unsafe {
374 zvec_rust_sys::zvec_vector_query_set_hnsw_params(self.handle, params.handle)
375 })?;
376 params.handle = std::ptr::null_mut();
378 Ok(())
379 }
380
381 pub fn set_ivf_params(&mut self, mut params: IvfQueryParams) -> Result<()> {
383 check_error(unsafe {
384 zvec_rust_sys::zvec_vector_query_set_ivf_params(self.handle, params.handle)
385 })?;
386 params.handle = std::ptr::null_mut();
387 Ok(())
388 }
389
390 pub fn set_flat_params(&mut self, mut params: FlatQueryParams) -> Result<()> {
392 check_error(unsafe {
393 zvec_rust_sys::zvec_vector_query_set_flat_params(self.handle, params.handle)
394 })?;
395 params.handle = std::ptr::null_mut();
396 Ok(())
397 }
398
399 pub fn set_diskann_params(&mut self, mut params: DiskannQueryParams) -> Result<()> {
401 check_error(unsafe {
402 zvec_rust_sys::zvec_vector_query_set_diskann_params(self.handle, params.handle)
403 })?;
404 params.handle = std::ptr::null_mut();
405 Ok(())
406 }
407
408 pub fn set_fts_params(&mut self, mut params: FtsQueryParams) -> Result<()> {
410 check_error(unsafe {
411 zvec_rust_sys::zvec_vector_query_set_fts_params(self.handle, params.handle)
412 })?;
413 params.handle = std::ptr::null_mut();
414 Ok(())
415 }
416
417 pub fn set_fts(&mut self, fts: &Fts) -> Result<()> {
419 check_error(unsafe { zvec_rust_sys::zvec_vector_query_set_fts(self.handle, fts.handle) })
420 }
421}
422
423impl Drop for SearchQuery {
424 fn drop(&mut self) {
425 if !self.handle.is_null() {
426 unsafe { zvec_rust_sys::zvec_vector_query_destroy(self.handle) };
427 }
428 }
429}
430
431pub struct SearchQueryBuilder {
433 field_name: Option<String>,
434 vector: Option<Vec<f32>>,
435 topk: i32,
436 filter: Option<String>,
437 include_vector: Option<bool>,
438 include_doc_id: Option<bool>,
439 output_fields: Option<Vec<String>>,
440 fts_query_string: Option<String>,
441 fts_match_string: Option<String>,
442}
443
444impl SearchQueryBuilder {
445 fn new() -> Self {
446 SearchQueryBuilder {
447 field_name: None,
448 vector: None,
449 topk: 10,
450 filter: None,
451 include_vector: None,
452 include_doc_id: None,
453 output_fields: None,
454 fts_query_string: None,
455 fts_match_string: None,
456 }
457 }
458
459 pub fn field_name(mut self, name: &str) -> Self {
461 self.field_name = Some(name.to_string());
462 self
463 }
464
465 pub fn vector(mut self, vector: &[f32]) -> Self {
467 self.vector = Some(vector.to_vec());
468 self
469 }
470
471 pub fn topk(mut self, topk: i32) -> Self {
473 self.topk = topk;
474 self
475 }
476
477 pub fn filter(mut self, filter: &str) -> Self {
479 self.filter = Some(filter.to_string());
480 self
481 }
482
483 pub fn include_vector(mut self, include: bool) -> Self {
485 self.include_vector = Some(include);
486 self
487 }
488
489 pub fn include_doc_id(mut self, include: bool) -> Self {
491 self.include_doc_id = Some(include);
492 self
493 }
494
495 pub fn output_fields(mut self, fields: &[&str]) -> Self {
497 self.output_fields = Some(fields.iter().map(|s| s.to_string()).collect());
498 self
499 }
500
501 pub fn fts_query_string(mut self, query: &str) -> Self {
503 self.fts_query_string = Some(query.to_string());
504 self
505 }
506
507 pub fn fts_match_string(mut self, match_str: &str) -> Self {
509 self.fts_match_string = Some(match_str.to_string());
510 self
511 }
512
513 pub fn build(self) -> Result<SearchQuery> {
515 let field_name = self.field_name.ok_or_else(|| Error {
516 code: ErrorCode::InvalidArgument,
517 message: "field_name is required".into(),
518 })?;
519 let vector = self.vector.ok_or_else(|| Error {
520 code: ErrorCode::InvalidArgument,
521 message: "vector is required".into(),
522 })?;
523
524 let mut query = SearchQuery::new(&field_name, &vector, self.topk)?;
525
526 if let Some(filter) = &self.filter {
527 query.set_filter(filter)?;
528 }
529 if let Some(include) = self.include_vector {
530 query.set_include_vector(include)?;
531 }
532 if let Some(include) = self.include_doc_id {
533 query.set_include_doc_id(include)?;
534 }
535 if let Some(fields) = &self.output_fields {
536 let field_refs: Vec<&str> = fields.iter().map(|s| s.as_str()).collect();
537 query.set_output_fields(&field_refs)?;
538 }
539 if self.fts_query_string.is_some() || self.fts_match_string.is_some() {
540 let mut fts = Fts::new()?;
541 if let Some(qs) = &self.fts_query_string {
542 fts.set_query_string(qs)?;
543 }
544 if let Some(ms) = &self.fts_match_string {
545 fts.set_match_string(ms)?;
546 }
547 query.set_fts(&fts)?;
548 }
549
550 Ok(query)
551 }
552}
553
554pub struct GroupBySearchQuery {
556 pub(crate) handle: *mut zvec_rust_sys::zvec_group_by_vector_query_t,
557}
558
559impl GroupBySearchQuery {
560 pub fn new(
562 field_name: &str,
563 group_by_field: &str,
564 vector: &[f32],
565 group_count: u32,
566 group_topk: u32,
567 ) -> Result<Self> {
568 let handle = unsafe { zvec_rust_sys::zvec_group_by_vector_query_create() };
569 if handle.is_null() {
570 return Err(Error {
571 code: ErrorCode::InternalError,
572 message: "failed to create group by vector query".into(),
573 });
574 }
575
576 let c_field = to_cstring(field_name)?;
577 let c_group_field = to_cstring(group_by_field)?;
578
579 check_error(unsafe {
580 zvec_rust_sys::zvec_group_by_vector_query_set_field_name(handle, c_field.as_ptr())
581 })?;
582 check_error(unsafe {
583 zvec_rust_sys::zvec_group_by_vector_query_set_group_by_field_name(
584 handle,
585 c_group_field.as_ptr(),
586 )
587 })?;
588 check_error(unsafe {
589 zvec_rust_sys::zvec_group_by_vector_query_set_query_vector(
590 handle,
591 vector.as_ptr() as *const c_void,
592 std::mem::size_of_val(vector),
593 )
594 })?;
595 check_error(unsafe {
596 zvec_rust_sys::zvec_group_by_vector_query_set_group_count(handle, group_count)
597 })?;
598 check_error(unsafe {
599 zvec_rust_sys::zvec_group_by_vector_query_set_topk_per_group(handle, group_topk)
600 })?;
601
602 Ok(GroupBySearchQuery { handle })
603 }
604
605 pub fn set_filter(&mut self, filter: &str) -> Result<()> {
607 let c_filter = to_cstring(filter)?;
608 check_error(unsafe {
609 zvec_rust_sys::zvec_group_by_vector_query_set_filter(self.handle, c_filter.as_ptr())
610 })
611 }
612
613 pub fn set_include_vector(&mut self, include: bool) -> Result<()> {
615 check_error(unsafe {
616 zvec_rust_sys::zvec_group_by_vector_query_set_include_vector(self.handle, include)
617 })
618 }
619
620 pub fn set_output_fields(&mut self, fields: &[&str]) -> Result<()> {
622 let c_fields: Vec<_> = fields
623 .iter()
624 .map(|f| to_cstring(f))
625 .collect::<Result<Vec<_>>>()?;
626 let c_ptrs: Vec<_> = c_fields.iter().map(|f| f.as_ptr()).collect();
627 check_error(unsafe {
628 zvec_rust_sys::zvec_group_by_vector_query_set_output_fields(
629 self.handle,
630 c_ptrs.as_ptr(),
631 c_ptrs.len(),
632 )
633 })
634 }
635
636 pub fn set_hnsw_params(&mut self, mut params: HnswQueryParams) -> Result<()> {
638 check_error(unsafe {
639 zvec_rust_sys::zvec_group_by_vector_query_set_hnsw_params(self.handle, params.handle)
640 })?;
641 params.handle = std::ptr::null_mut();
643 Ok(())
644 }
645
646 pub fn set_ivf_params(&mut self, mut params: IvfQueryParams) -> Result<()> {
648 check_error(unsafe {
649 zvec_rust_sys::zvec_group_by_vector_query_set_ivf_params(self.handle, params.handle)
650 })?;
651 params.handle = std::ptr::null_mut();
653 Ok(())
654 }
655
656 pub fn set_flat_params(&mut self, mut params: FlatQueryParams) -> Result<()> {
658 check_error(unsafe {
659 zvec_rust_sys::zvec_group_by_vector_query_set_flat_params(self.handle, params.handle)
660 })?;
661 params.handle = std::ptr::null_mut();
663 Ok(())
664 }
665
666 pub fn set_diskann_params(&mut self, mut params: DiskannQueryParams) -> Result<()> {
668 check_error(unsafe {
669 zvec_rust_sys::zvec_group_by_vector_query_set_diskann_params(self.handle, params.handle)
670 })?;
671 params.handle = std::ptr::null_mut();
673 Ok(())
674 }
675}
676
677impl Drop for GroupBySearchQuery {
678 fn drop(&mut self) {
679 if !self.handle.is_null() {
680 unsafe { zvec_rust_sys::zvec_group_by_vector_query_destroy(self.handle) };
681 }
682 }
683}
684
685#[cfg(test)]
686mod tests {
687 use super::*;
688
689 #[test]
690 fn test_vector_query_builder_default_values() {
691 let builder = SearchQueryBuilder::new();
692 assert!(builder.field_name.is_none());
693 assert!(builder.vector.is_none());
694 assert_eq!(builder.topk, 10);
695 assert!(builder.filter.is_none());
696 assert!(builder.include_vector.is_none());
697 assert!(builder.include_doc_id.is_none());
698 assert!(builder.output_fields.is_none());
699 }
700
701 #[test]
702 fn test_vector_query_builder_setters() {
703 let builder = SearchQueryBuilder::new()
704 .field_name("test_field")
705 .vector(&[1.0, 2.0, 3.0])
706 .topk(5)
707 .filter("age > 18")
708 .include_vector(true)
709 .include_doc_id(false)
710 .output_fields(&["name", "age"]);
711
712 assert_eq!(builder.field_name, Some("test_field".to_string()));
713 assert_eq!(builder.vector, Some(vec![1.0, 2.0, 3.0]));
714 assert_eq!(builder.topk, 5);
715 assert_eq!(builder.filter, Some("age > 18".to_string()));
716 assert_eq!(builder.include_vector, Some(true));
717 assert_eq!(builder.include_doc_id, Some(false));
718 assert_eq!(
719 builder.output_fields,
720 Some(vec!["name".to_string(), "age".to_string()])
721 );
722 }
723
724 #[test]
725 fn test_vector_query_builder_build_missing_field_name() {
726 let builder = SearchQueryBuilder::new().vector(&[1.0, 2.0, 3.0]);
727
728 let result = builder.build();
729 assert!(result.is_err());
730 if let Err(e) = result {
731 assert_eq!(e.code, ErrorCode::InvalidArgument);
732 assert!(e.message.contains("field_name is required"));
733 }
734 }
735
736 #[test]
737 fn test_vector_query_builder_build_missing_vector() {
738 let builder = SearchQueryBuilder::new().field_name("test_field");
739
740 let result = builder.build();
741 assert!(result.is_err());
742 if let Err(e) = result {
743 assert_eq!(e.code, ErrorCode::InvalidArgument);
744 assert!(e.message.contains("vector is required"));
745 }
746 }
747
748 #[test]
749 fn test_vector_query_builder_builder_method() {
750 let builder = SearchQuery::builder();
751 assert!(builder.field_name.is_none());
752 assert!(builder.vector.is_none());
753 assert_eq!(builder.topk, 10);
754 }
755
756 #[test]
757 fn test_vector_query_builder_partial_setters() {
758 let builder = SearchQueryBuilder::new()
759 .field_name("test_field")
760 .vector(&[1.0, 2.0])
761 .filter("status = 'active'");
762 assert_eq!(builder.field_name, Some("test_field".to_string()));
763 assert_eq!(builder.vector, Some(vec![1.0, 2.0]));
764 assert_eq!(builder.filter, Some("status = 'active'".to_string()));
765 assert!(builder.include_vector.is_none());
766 assert!(builder.output_fields.is_none());
767 }
768
769 #[test]
770 fn test_vector_query_builder_empty_vector() {
771 let builder = SearchQueryBuilder::new()
772 .field_name("test_field")
773 .vector(&[]);
774 assert_eq!(builder.vector, Some(vec![]));
775 }
776
777 #[test]
778 fn test_vector_query_builder_empty_output_fields() {
779 let builder = SearchQueryBuilder::new()
780 .field_name("test_field")
781 .vector(&[1.0])
782 .output_fields(&[]);
783 assert_eq!(builder.output_fields, Some(vec![]));
784 }
785
786 #[test]
787 fn test_vector_query_builder_topk_zero() {
788 let builder = SearchQueryBuilder::new()
789 .field_name("test_field")
790 .vector(&[1.0])
791 .topk(0);
792 assert_eq!(builder.topk, 0);
793 }
794
795 #[test]
796 fn test_vector_query_builder_topk_negative() {
797 let builder = SearchQueryBuilder::new()
798 .field_name("test_field")
799 .vector(&[1.0])
800 .topk(-1);
801 assert_eq!(builder.topk, -1);
802 }
803
804 #[test]
805 fn test_vector_query_builder_overwrite_field_name() {
806 let builder = SearchQueryBuilder::new()
807 .field_name("first_field")
808 .field_name("second_field");
809 assert_eq!(builder.field_name, Some("second_field".to_string()));
810 }
811
812 #[test]
813 fn test_vector_query_builder_large_vector() {
814 let large_vector: Vec<f32> = (0..1024).map(|i| i as f32).collect();
815 let builder = SearchQueryBuilder::new()
816 .field_name("test_field")
817 .vector(&large_vector);
818 assert_eq!(builder.vector.as_ref().unwrap().len(), 1024);
819 }
820
821 #[test]
822 fn test_fts_query_no_vector() {
823 let mut fts = Fts::new().expect("create fts payload");
826 fts.set_match_string("hello world")
827 .expect("set match string");
828
829 let query = SearchQuery::fts("content", &fts, 10);
830 assert!(
831 query.is_ok(),
832 "pure FTS query should build without a vector"
833 );
834 assert!(!unsafe { query.unwrap().as_raw() }.is_null());
835 }
836
837 #[test]
838 fn test_diskann_query_params_create_and_getters() {
839 let mut params = DiskannQueryParams::new(200);
840 assert_eq!(params.list_size(), 200);
841 params.set_list_size(300).expect("set list_size");
842 assert_eq!(params.list_size(), 300);
843 }
844}