blob: ded48f63bc0945dade931bf7915ce97e765ef52c [file]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
"""Vector index queries delegated to the Rust reader."""
from pypaimon.globalindex.global_index_reader import GlobalIndexReader, _completed_future
from pypaimon.globalindex.vector_search_result import DictBasedScoredIndexResult
from pypaimon.globalindex.vindex_input import VindexReaderResources, _filter_bytes
def _native_reader_type():
from pypaimon.execution.native.runtime import native_runtime_available
if not native_runtime_available():
return None
from pypaimon_rust.datafusion import VindexVectorGlobalIndexReader
return VindexVectorGlobalIndexReader
def create_native_vindex_reader(file_io, index_path, io_metas, options=None):
reader_type = _native_reader_type()
if reader_type is None:
return None
return NativeVindexVectorGlobalIndexReader(file_io, index_path, io_metas, options, reader_type)
class NativeVindexVectorGlobalIndexReader(VindexReaderResources, GlobalIndexReader):
"""Rust owns vector validation, filtering, query options and scoring."""
def __init__(self, file_io, index_path, io_metas, options, reader_type):
super().__init__(file_io, index_path, io_metas, options)
self._reader_type = reader_type
def _create_reader(self, index_input, file_path):
return self._reader_type(
index_input, file_path, self._io_meta.file_size,
{str(key): str(value) for key, value in self._options.items()})
def visit_vector_search(self, vector_search):
results = self._run_search(
[vector_search.vector],
vector_search.limit,
vector_search.include_row_ids,
vector_search.options,
)
return _completed_future(results[0])
def visit_batch_vector_search(self, batch_vector_search):
results = self._run_search(
batch_vector_search.vectors,
batch_vector_search.limit,
batch_vector_search.include_row_ids,
batch_vector_search.options,
)
return _completed_future(results)
def _run_search(self, vectors, limit, include_row_ids, query_options):
self._ensure_loaded()
results = self._reader.search(
vectors, limit, filter_bytes=_filter_bytes(include_row_ids),
options={str(key): str(value) for key, value in (query_options or {}).items()})
return [DictBasedScoredIndexResult(scores) if scores else None for scores in results]
def vector_metric(self):
self._ensure_loaded()
return self._reader.metric()