@@ -136,3 +136,89 @@ async def test_qdrant_register_and_unregister_vector_db(
136136 await qdrant_adapter .unregister_vector_db (vector_db_id )
137137 assert not (await qdrant_adapter .client .collection_exists (vector_db_id ))
138138 assert len ((await qdrant_adapter .client .get_collections ()).collections ) == 0
139+
140+
141+ # Keyword search tests
142+ async def test_query_chunks_keyword_search (qdrant_vec_index , sample_chunks , sample_embeddings ):
143+ """Test keyword search functionality in Qdrant."""
144+ await qdrant_vec_index .add_chunks (sample_chunks , sample_embeddings )
145+ query_string = "Sentence 5"
146+ response = await qdrant_vec_index .query_keyword (query_string = query_string , k = 3 , score_threshold = 0.0 )
147+
148+ assert isinstance (response , QueryChunksResponse )
149+ assert len (response .chunks ) > 0 , f"Expected some chunks, but got { len (response .chunks )} "
150+
151+ non_existent_query_str = "blablabla"
152+ response_no_results = await qdrant_vec_index .query_keyword (
153+ query_string = non_existent_query_str , k = 1 , score_threshold = 0.0
154+ )
155+
156+ assert isinstance (response_no_results , QueryChunksResponse )
157+ assert len (response_no_results .chunks ) == 0 , f"Expected 0 results, but got { len (response_no_results .chunks )} "
158+
159+
160+ async def test_query_chunks_keyword_search_k_greater_than_results (qdrant_vec_index , sample_chunks , sample_embeddings ):
161+ """Test keyword search when k is greater than available results."""
162+ await qdrant_vec_index .add_chunks (sample_chunks , sample_embeddings )
163+
164+ query_str = "Sentence 1 from document 0" # Should match only one chunk
165+ response = await qdrant_vec_index .query_keyword (k = 5 , score_threshold = 0.0 , query_string = query_str )
166+
167+ assert isinstance (response , QueryChunksResponse )
168+ assert 0 < len (response .chunks ) < 5 , f"Expected results between [1, 4], got { len (response .chunks )} "
169+ assert any ("Sentence 1 from document 0" in chunk .content for chunk in response .chunks ), "Expected chunk not found"
170+
171+
172+ async def test_query_chunks_keyword_search_score_threshold (qdrant_vec_index , sample_chunks , sample_embeddings ):
173+ """Test keyword search with score threshold filtering."""
174+ await qdrant_vec_index .add_chunks (sample_chunks , sample_embeddings )
175+
176+ query_string = "Sentence 5"
177+
178+ # Test with low threshold (should return results)
179+ response_low_threshold = await qdrant_vec_index .query_keyword (query_string = query_string , k = 3 , score_threshold = 0.0 )
180+ assert len (response_low_threshold .chunks ) > 0
181+
182+ # Test with negative threshold (should return results since scores are 0.0)
183+ response_negative_threshold = await qdrant_vec_index .query_keyword (
184+ query_string = query_string , k = 3 , score_threshold = - 1.0
185+ )
186+ assert len (response_negative_threshold .chunks ) > 0
187+
188+
189+ async def test_query_chunks_keyword_search_edge_cases (qdrant_vec_index , sample_chunks , sample_embeddings ):
190+ """Test keyword search edge cases."""
191+ await qdrant_vec_index .add_chunks (sample_chunks , sample_embeddings )
192+
193+ # Test with empty string
194+ response_empty = await qdrant_vec_index .query_keyword (query_string = "" , k = 3 , score_threshold = 0.0 )
195+ assert isinstance (response_empty , QueryChunksResponse )
196+
197+ # Test with very long query string
198+ long_query = "a" * 1000
199+ response_long = await qdrant_vec_index .query_keyword (query_string = long_query , k = 3 , score_threshold = 0.0 )
200+ assert isinstance (response_long , QueryChunksResponse )
201+
202+ # Test with special characters
203+ special_query = "!@#$%^&*()_+-=[]{}|;':\" ,./<>?"
204+ response_special = await qdrant_vec_index .query_keyword (query_string = special_query , k = 3 , score_threshold = 0.0 )
205+ assert isinstance (response_special , QueryChunksResponse )
206+
207+
208+ async def test_query_chunks_keyword_search_metadata_preservation (
209+ qdrant_vec_index , sample_chunks_with_metadata , sample_embeddings_with_metadata
210+ ):
211+ """Test that keyword search preserves chunk metadata."""
212+ await qdrant_vec_index .add_chunks (sample_chunks_with_metadata , sample_embeddings_with_metadata )
213+
214+ query_string = "Sentence 0"
215+ response = await qdrant_vec_index .query_keyword (query_string = query_string , k = 2 , score_threshold = 0.0 )
216+
217+ assert len (response .chunks ) > 0
218+ for chunk in response .chunks :
219+ # Check that metadata is preserved
220+ assert hasattr (chunk , "metadata" ) or hasattr (chunk , "chunk_metadata" )
221+ if hasattr (chunk , "chunk_metadata" ) and chunk .chunk_metadata :
222+ assert chunk .chunk_metadata .document_id is not None
223+ assert chunk .chunk_metadata .chunk_id is not None
224+ assert chunk .chunk_metadata .source is not None
0 commit comments