(
&self,
task: &ExecutionTask,
tid: u64,
collection: &str,
index_key: &(crate::types::TenantId, String),
ivf: &crate::engine::vector::ivf::IvfPqIndex,
| 288 | /// Search an IVF-PQ index with optional bitmap post-filtering. |
| 289 | #[allow(clippy::too_many_arguments)] |
| 290 | fn search_ivf( |
| 291 | &self, |
| 292 | task: &ExecutionTask, |
| 293 | tid: u64, |
| 294 | collection: &str, |
| 295 | index_key: &(crate::types::TenantId, String), |
| 296 | ivf: &crate::engine::vector::ivf::IvfPqIndex, |
| 297 | query_vector: &[f32], |
| 298 | top_k: usize, |
| 299 | filter_bitmap: Option<&nodedb_types::SurrogateBitmap>, |
| 300 | rls_filters: &[u8], |
| 301 | ) -> Response { |
| 302 | if ivf.is_empty() { |
| 303 | return self.response_with_payload(task, b"[]".to_vec()); |
| 304 | } |
| 305 | let fetch_k = if filter_bitmap.is_some() || !rls_filters.is_empty() { |
| 306 | top_k * self.query_tuning.bitmap_over_fetch_factor.max(2) |
| 307 | } else { |
| 308 | top_k |
| 309 | }; |
| 310 | let results = ivf.search(query_vector, fetch_k); |
| 311 | let surrogate_source = self.vector_collections.get(index_key); |
| 312 | |
| 313 | let mut hits: Vec<_> = results |
| 314 | .iter() |
| 315 | .map(|r| build_search_hit(surrogate_source, r.id, r.distance)) |
| 316 | .collect(); |
| 317 | |
| 318 | if let Some(surrogate_bm) = filter_bitmap { |
| 319 | // Bitmap is a set of surrogates; hit.id is now the surrogate. |
| 320 | hits.retain(|h| surrogate_bm.0.contains(h.id)); |
| 321 | } |
| 322 | if !rls_filters.is_empty() { |
| 323 | // CP-side translator runs the predicate; DP only attaches body. |
| 324 | hits = hits |
| 325 | .into_iter() |
| 326 | .map(|h| self.attach_body(tid, collection, true, h)) |
| 327 | .collect(); |
| 328 | } else { |
| 329 | hits.truncate(top_k); |
| 330 | } |
| 331 | |
| 332 | if let Some(ref m) = self.metrics { |
| 333 | m.record_vector_search(0); |
| 334 | m.record_query_by_engine("vector"); |
| 335 | } |
| 336 | encode_hits_response(self, task, &hits) |
| 337 | } |
| 338 | |
| 339 | /// Multi-vector search: query all named vector fields in a collection, |
| 340 | /// fuse results via RRF. |
no test coverage detected