@@ -66,10 +66,10 @@ std::vector<std::pair<float, search::GlobalDocId>> GlobalVectorIndex::SearchKnnF
6666 return index->Knn (knn->vec .first .get ());
6767}
6868
69- std::vector<SearchResult> GlobalVectorIndex::Search (const search::AstKnnNode* knn_node,
70- const std::vector<SearchResult>& filter_docs,
71- const CommandContext& cmd_cntx ,
72- const SearchParams& params) {
69+ std::vector<SearchResult> GlobalVectorIndex::Search (
70+ const search::AstKnnNode* knn_node, const std::vector<SearchResult>& filter_docs,
71+ const std::optional<search::KnnScoreSortOption>& knn_score_option ,
72+ const CommandContext& cmd_cntx, const SearchParams& params) {
7373 std::vector<SearchResult> results (1 );
7474
7575 std::optional<std::vector<search::GlobalDocId>> filter_docs_global_ids = std::nullopt ;
@@ -105,7 +105,8 @@ std::vector<SearchResult> GlobalVectorIndex::Search(const search::AstKnnNode* kn
105105 return results;
106106 }
107107
108- std::vector<SerializedSearchDoc> knn_result_docs (knn_results.size ());
108+ std::vector<SerializedSearchDoc> knn_result_docs;
109+ knn_result_docs.reserve (knn_results.size ());
109110
110111 // Group by shard with minimal allocations
111112 std::vector<std::vector<std::pair<float , search::DocId>>> shard_doc_ids (shard_size);
@@ -148,28 +149,56 @@ std::vector<SearchResult> GlobalVectorIndex::Search(const search::AstKnnNode* kn
148149 // Cache schema reference to avoid repeated lookups
149150 const auto & schema = index->GetInfo ().base_index .schema ;
150151
152+ auto & sort_option = params.sort_option ;
153+ bool need_fetch_sort_field = false ;
154+
155+ if (sort_option) {
156+ need_fetch_sort_field = !params.sort_option ->IsSame (*knn_score_option);
157+ }
158+
151159 // Optimize serialization based on query type
152160 if (params.ShouldReturnAllFields ()) {
153161 // Full serialization for full queries
154162 for (const auto & [score, doc_id] : shard_requests) {
155163 if (auto entry = index->LoadEntry (doc_id, t->GetOpArgs (es))) {
156164 auto & [key, accessor] = *entry;
157165 auto fields = accessor->Serialize (schema);
166+
167+ search::SortableValue sort_score = std::monostate{};
168+
169+ if (need_fetch_sort_field) {
170+ sort_score = fields[params.sort_option ->field .Name ()];
171+ }
172+
158173 docs_for_shard.push_back (
159- {doc_id, std::string{key}, std::move (fields), score, std::monostate{} });
174+ {doc_id, std::string{key}, std::move (fields), score, sort_score });
160175 }
161176 }
162177 } else {
163178 // Selective field serialization
164179 const auto & return_fields = params.return_fields .value_or (std::vector<FieldReference>{});
180+ bool sort_field_in_return_fields = false ;
181+
182+ if (need_fetch_sort_field) {
183+ for (auto & field_reference : return_fields) {
184+ sort_field_in_return_fields = field_reference.Name () == sort_option->field .Name ();
185+ }
186+ }
187+
165188 for (const auto & [score, doc_id] : shard_requests) {
166189 if (auto entry = index->LoadEntry (doc_id, t->GetOpArgs (es))) {
167190 auto & [key, accessor] = *entry;
168191 auto fields = return_fields.empty () ? SearchDocData{}
169192 // NOCONTENT query - no fields needed
170193 : accessor->Serialize (schema, return_fields);
194+
195+ search::SortableValue sort_score = std::monostate{};
196+ if (sort_field_in_return_fields && need_fetch_sort_field) {
197+ sort_score = fields[params.sort_option ->field .Name ()];
198+ }
199+
171200 docs_for_shard.push_back (
172- {doc_id, std::string{key}, std::move (fields), score, std::monostate{} });
201+ {doc_id, std::string{key}, std::move (fields), score, sort_score });
173202 }
174203 }
175204 }
@@ -182,6 +211,12 @@ std::vector<SearchResult> GlobalVectorIndex::Search(const search::AstKnnNode* kn
182211 std::make_move_iterator (docs.end ()));
183212 }
184213
214+ auto cb = [](SerializedSearchDoc& l, SerializedSearchDoc& r) {
215+ return l.knn_score > r.knn_score ;
216+ };
217+ partial_sort (knn_result_docs.begin (), knn_result_docs.begin () + knn_result_docs.size () / 2 ,
218+ knn_result_docs.end (), cb);
219+
185220 results[0 ].total_hits = knn_results.size ();
186221 results[0 ].docs = std::move (knn_result_docs);
187222 return results;
@@ -230,6 +265,11 @@ std::shared_ptr<GlobalVectorIndex> GlobalVectorIndexRegistry::GetVectorIndex(
230265 return it != indices_.end () ? it->second : nullptr ;
231266}
232267
268+ void GlobalVectorIndexRegistry::Reset () {
269+ std::unique_lock<std::shared_mutex> lock (registry_mutex_);
270+ indices_.clear ();
271+ }
272+
233273std::string GlobalVectorIndexRegistry::MakeKey (std::string_view index_name,
234274 std::string_view field_name) const {
235275 return absl::StrCat (index_name, " :" , field_name);
0 commit comments