| 2116 | } |
| 2117 | |
| 2118 | [[nodiscard]] DatasetPtr |
| 2119 | HGraph::SearchWithRequest(const SearchRequest& request) const { |
| 2120 | SearchStatistics stats; |
| 2121 | QueryContext ctx{.alloc = this->allocator_, .stats = &stats}; |
| 2122 | if (request.search_allocator_ != nullptr) { |
| 2123 | ctx.alloc = request.search_allocator_; |
| 2124 | } |
| 2125 | |
| 2126 | const auto& query = request.query_; |
| 2127 | int64_t query_dim = query->GetDim(); |
| 2128 | auto k = request.topk_; |
| 2129 | if (data_type_ != DataTypes::DATA_TYPE_SPARSE) { |
| 2130 | CHECK_ARGUMENT( |
| 2131 | query_dim == dim_, |
| 2132 | fmt::format("query.dim({}) must be equal to index.dim({})", query_dim, dim_)); |
| 2133 | } |
| 2134 | |
| 2135 | auto params = HGraphSearchParameters::FromJson(request.params_str_); |
| 2136 | |
| 2137 | auto ef_search_threshold = std::max(AMPLIFICATION_FACTOR * k, 1000L); |
| 2138 | CHECK_ARGUMENT( // NOLINT |
| 2139 | (1 <= params.ef_search) and (params.ef_search <= ef_search_threshold), |
| 2140 | fmt::format("ef_search({}) must in range[1, {}]", params.ef_search, ef_search_threshold)); |
| 2141 | |
| 2142 | std::shared_lock shared_lock(this->global_mutex_); |
| 2143 | // check k |
| 2144 | CHECK_ARGUMENT(k > 0, fmt::format("k({}) must be greater than 0", k)); |
| 2145 | k = std::min(k, GetNumElements()); |
| 2146 | |
| 2147 | // check query vector |
| 2148 | CHECK_ARGUMENT(query->GetNumElements() == 1, "query dataset should contain 1 vector only"); |
| 2149 | |
| 2150 | InnerSearchParam search_param; |
| 2151 | search_param.ep = this->entry_point_id_; |
| 2152 | search_param.topk = 1; |
| 2153 | search_param.ef = 1; |
| 2154 | search_param.is_inner_id_allowed = nullptr; |
| 2155 | |
| 2156 | if (search_param.ep == INVALID_ENTRY_POINT) { |
| 2157 | return make_empty_dataset_with_stats(); |
| 2158 | } |
| 2159 | |
| 2160 | auto vt = this->pool_->TakeOne(); |
| 2161 | |
| 2162 | const auto* raw_query = get_data(query); |
| 2163 | for (auto i = static_cast<int64_t>(this->route_graphs_.size() - 1); i >= 0; --i) { |
| 2164 | auto result = this->search_one_graph( |
| 2165 | raw_query, this->route_graphs_[i], this->basic_flatten_codes_, search_param, vt, &ctx); |
| 2166 | search_param.ep = result->Top().second; |
| 2167 | } |
| 2168 | |
| 2169 | FilterPtr ft = nullptr; |
| 2170 | if (request.filter_ != nullptr) { |
| 2171 | if (params.use_extra_info_filter) { |
| 2172 | ft = std::make_shared<ExtraInfoWrapperFilter>(request.filter_, this->extra_infos_); |
| 2173 | } else { |
| 2174 | ft = std::make_shared<InnerIdWrapperFilter>(request.filter_, *this->label_table_); |
| 2175 | } |
no test coverage detected