@@ -84,7 +84,7 @@ def __repr__(self):
8484class QueryResultsAggregationEmptyResultsError (Exception ):
8585 def __init__ (self , namespace : str ):
8686 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. "
8888 )
8989
9090
@@ -111,7 +111,7 @@ def __init__(self, top_k: int):
111111 self .is_dotproduct = None
112112 self .read = False
113113
114- def __is_dotproduct_index (self , matches ):
114+ def _is_dotproduct_index (self , matches ):
115115 # The interpretation of the score depends on the similar metric used.
116116 # Unlike other index types, in indexes configured for dotproduct,
117117 # 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):
121121 return False
122122 return True
123123
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+
124138 def add_results (self , results : QueryResponse ):
125139 if self .read :
126140 # This is mainly just to sanity check in test cases which get quite confusing
@@ -132,24 +146,18 @@ def add_results(self, results: QueryResponse):
132146 ns = results .get ("namespace" )
133147 self .usage_read_units += results .get ("usage" , {}).get ("readUnits" , 0 )
134148
149+ if len (matches ) == 0 :
150+ raise QueryResultsAggregationEmptyResultsError (ns )
151+
135152 if self .is_dotproduct is None :
136- if len (matches ) == 0 :
137- raise QueryResultsAggregationEmptyResultsError (ns )
138153 if len (matches ) == 1 :
139154 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 )
141156
142- print ("is_dotproduct:" , self .is_dotproduct )
143157 if self .is_dotproduct :
144- raise NotImplementedError ( "Dotproduct indexes are not yet supported." )
158+ self . _process_matches ( matches , ns , self . _dotproduct_heap_item )
145159 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 )
153161
154162 def get_results (self ) -> CompositeQueryResults :
155163 if self .read :
0 commit comments