@@ -84,7 +84,7 @@ def __repr__(self):
84
84
class QueryResultsAggregationEmptyResultsError (Exception ):
85
85
def __init__ (self , namespace : str ):
86
86
super ().__init__ (
87
- f"Cannot infer metric type from empty query results. Query result for namespace '{ namespace } ' is empty. Have you spelled the namespace name correctly? "
87
+ f"Query results for namespace '{ namespace } ' were empty. Check that you have upserted vectors into this namespace (see describe_index_stats) and that the namespace name is spelled correctly. "
88
88
)
89
89
90
90
@@ -111,7 +111,7 @@ def __init__(self, top_k: int):
111
111
self .is_dotproduct = None
112
112
self .read = False
113
113
114
- def __is_dotproduct_index (self , matches ):
114
+ def _is_dotproduct_index (self , matches ):
115
115
# The interpretation of the score depends on the similar metric used.
116
116
# Unlike other index types, in indexes configured for dotproduct,
117
117
# a higher score is better. We have to infer this is the case by inspecting
@@ -121,6 +121,20 @@ def __is_dotproduct_index(self, matches):
121
121
return False
122
122
return True
123
123
124
+ def _dotproduct_heap_item (self , match , ns ):
125
+ return (match .get ("score" ), - self .insertion_counter , match , ns )
126
+
127
+ def _non_dotproduct_heap_item (self , match , ns ):
128
+ return (- match .get ("score" ), - self .insertion_counter , match , ns )
129
+
130
+ def _process_matches (self , matches , ns , heap_item_fn ):
131
+ for match in matches :
132
+ self .insertion_counter += 1
133
+ if len (self .heap ) < self .top_k :
134
+ heapq .heappush (self .heap , heap_item_fn (match , ns ))
135
+ else :
136
+ heapq .heappushpop (self .heap , heap_item_fn (match , ns ))
137
+
124
138
def add_results (self , results : QueryResponse ):
125
139
if self .read :
126
140
# This is mainly just to sanity check in test cases which get quite confusing
@@ -132,24 +146,18 @@ def add_results(self, results: QueryResponse):
132
146
ns = results .get ("namespace" )
133
147
self .usage_read_units += results .get ("usage" , {}).get ("readUnits" , 0 )
134
148
149
+ if len (matches ) == 0 :
150
+ raise QueryResultsAggregationEmptyResultsError (ns )
151
+
135
152
if self .is_dotproduct is None :
136
- if len (matches ) == 0 :
137
- raise QueryResultsAggregationEmptyResultsError (ns )
138
153
if len (matches ) == 1 :
139
154
raise QueryResultsAggregregatorNotEnoughResultsError (self .top_k , len (matches ))
140
- self .is_dotproduct = self .__is_dotproduct_index (matches )
155
+ self .is_dotproduct = self ._is_dotproduct_index (matches )
141
156
142
- print ("is_dotproduct:" , self .is_dotproduct )
143
157
if self .is_dotproduct :
144
- raise NotImplementedError ( "Dotproduct indexes are not yet supported." )
158
+ self . _process_matches ( matches , ns , self . _dotproduct_heap_item )
145
159
else :
146
- for match in matches :
147
- self .insertion_counter += 1
148
- score = match .get ("score" )
149
- if len (self .heap ) < self .top_k :
150
- heapq .heappush (self .heap , (- score , - self .insertion_counter , match , ns ))
151
- else :
152
- heapq .heappushpop (self .heap , (- score , - self .insertion_counter , match , ns ))
160
+ self ._process_matches (matches , ns , self ._non_dotproduct_heap_item )
153
161
154
162
def get_results (self ) -> CompositeQueryResults :
155
163
if self .read :
0 commit comments