1- import type { BaseNode , Metadata } from "@llamaindex/core/schema" ;
1+ import { type BaseNode , type Metadata } from "@llamaindex/core/schema" ;
22import {
33 BaseVectorStore ,
44 FilterCondition ,
55 FilterOperator ,
6+ metadataDictToNode ,
7+ nodeToMetadata ,
68 type MetadataFilters ,
79 type VectorStoreBaseParams ,
810 type VectorStoreQuery ,
911 type VectorStoreQueryResult ,
1012} from "@llamaindex/core/vector-store" ;
11-
12- import {
13- metadataDictToNode ,
14- nodeToMetadata ,
15- } from "@llamaindex/core/vector-store" ;
1613import type { QdrantClientParams , Schemas } from "@qdrant/js-client-rest" ;
1714import { QdrantClient } from "@qdrant/js-client-rest" ;
1815
1916type QdrantFilter = Schemas [ "Filter" ] ;
2017type QdrantMustConditions = QdrantFilter [ "must" ] ;
2118type QdrantQueryResult = Schemas [ "QueryResponse" ] ;
2219type QdrantSearchParams = Schemas [ "SearchParams" ] ;
20+ type QdrantCondition = Schemas [ "Condition" ] ; // Added for type safety
2321
2422type PointStruct = {
2523 id : string ;
26- payload : Record < string , string > ;
24+ payload : Metadata ; // Use Metadata type instead of any
2725 vector : number [ ] ;
2826} ;
2927
@@ -35,6 +33,14 @@ type QdrantParams = {
3533 batchSize ?: number ;
3634} & VectorStoreBaseParams ;
3735
36+ /**
37+ * Interface for Qdrant-specific query options to avoid 'any' casting.
38+ */
39+ interface QdrantQueryOptions {
40+ qdrant_filters ?: QdrantFilter ;
41+ qdrant_search_params ?: QdrantSearchParams ;
42+ }
43+
3844/**
3945 * Qdrant vector store.
4046 */
@@ -144,7 +150,7 @@ export class QdrantVectorStore extends BaseVectorStore {
144150 const points : PointStruct [ ] = [ ] ;
145151 const ids = [ ] ;
146152
147- for ( let i = 0 ; i < nodes . length ; i ++ ) {
153+ for ( let i = 0 ; i < nodes . length ; ) {
148154 const nodeIds = [ ] ;
149155 const vectors = [ ] ;
150156 const payloads = [ ] ;
@@ -269,14 +275,9 @@ export class QdrantVectorStore extends BaseVectorStore {
269275 query : VectorStoreQuery < QdrantSearchParams | undefined > ,
270276 options ?: object ,
271277 ) : Promise < VectorStoreQueryResult > {
272- const qdrantFilters =
273- options && "qdrant_filters" in options
274- ? options . qdrant_filters
275- : undefined ;
276- const qdrantSearchParams =
277- options && "qdrant_search_params" in options
278- ? options . qdrant_search_params
279- : undefined ;
278+ const qdrantOptions = options as QdrantQueryOptions ; // Cast to specific interface
279+ const qdrantFilters = qdrantOptions ?. qdrant_filters ;
280+ const qdrantSearchParams = qdrantOptions ?. qdrant_search_params ;
280281
281282 let queryFilters : QdrantFilter | undefined ;
282283 let searchParams : QdrantSearchParams | undefined ;
@@ -317,7 +318,7 @@ export class QdrantVectorStore extends BaseVectorStore {
317318function buildQueryFilter ( query : VectorStoreQuery ) : QdrantFilter | undefined {
318319 if ( ! query . docIds && ! query . queryStr && ! query . filters ) return undefined ;
319320
320- const mustConditions : QdrantMustConditions = [ ] ;
321+ const mustConditions : QdrantCondition [ ] = [ ] ; // Explicitly typed
321322 if ( query . docIds ) {
322323 mustConditions . push ( {
323324 key : "doc_id" ,
@@ -327,10 +328,14 @@ function buildQueryFilter(query: VectorStoreQuery): QdrantFilter | undefined {
327328
328329 const metadataFilters = toQdrantMetadataFilters ( query . filters ) ;
329330 if ( metadataFilters ) {
330- mustConditions . push ( metadataFilters ) ;
331+ if ( metadataFilters . must ) {
332+ mustConditions . push ( ...metadataFilters . must ) ;
333+ } else {
334+ mustConditions . push ( metadataFilters ) ;
335+ }
331336 }
332337
333- return { must : mustConditions } ;
338+ return mustConditions . length > 0 ? { must : mustConditions } : undefined ;
334339}
335340
336341function buildSearchParams (
@@ -355,74 +360,46 @@ function toQdrantMetadataFilters(
355360) : QdrantFilter | undefined {
356361 if ( ! subFilters ?. filters . length ) return undefined ;
357362
358- const conditions : QdrantMustConditions = [ ] ;
363+ const conditions : QdrantCondition [ ] = [ ] ; // Explicitly typed
359364
360365 for ( const subfilter of subFilters . filters ) {
361- if ( subfilter . operator === FilterOperator . EQ ) {
362- if ( typeof subfilter . value === "number" ) {
363- conditions . push ( {
364- key : subfilter . key ,
365- range : {
366- gte : subfilter . value ,
367- lte : subfilter . value ,
368- } ,
369- } ) ;
366+ const { key, value, operator } = subfilter ;
367+
368+ if ( operator === FilterOperator . EQ ) {
369+ if ( typeof value === "number" ) {
370+ conditions . push ( { key, range : { gte : value , lte : value } } ) ;
370371 } else {
371372 conditions . push ( {
372- key : subfilter . key ,
373- match : { value : subfilter . value } ,
373+ key,
374+ match : { value : value as string | number | boolean } ,
374375 } ) ;
375376 }
376- } else if ( subfilter . operator === FilterOperator . LT ) {
377- conditions . push ( {
378- key : subfilter . key ,
379- range : { lt : subfilter . value } ,
380- } ) ;
381- } else if ( subfilter . operator === FilterOperator . GT ) {
382- conditions . push ( {
383- key : subfilter . key ,
384- range : { gt : subfilter . value } ,
385- } ) ;
386- } else if ( subfilter . operator === FilterOperator . GTE ) {
387- conditions . push ( {
388- key : subfilter . key ,
389- range : { gte : subfilter . value } ,
390- } ) ;
391- } else if ( subfilter . operator === FilterOperator . LTE ) {
392- conditions . push ( {
393- key : subfilter . key ,
394- range : { lte : subfilter . value } ,
395- } ) ;
396- } else if ( subfilter . operator === FilterOperator . TEXT_MATCH ) {
397- conditions . push ( {
398- key : subfilter . key ,
399- match : { text : subfilter . value } ,
400- } ) ;
401- } else if ( subfilter . operator === FilterOperator . NE ) {
402- conditions . push ( {
403- key : subfilter . key ,
404- match : { except : [ subfilter . value ] } ,
405- } ) ;
406- } else if ( subfilter . operator === FilterOperator . IN ) {
407- const values = Array . isArray ( subfilter . value )
408- ? subfilter . value . map ( String )
409- : String ( subfilter . value ) . split ( "," ) ;
410- conditions . push ( {
411- key : subfilter . key ,
412- match : { any : values } ,
413- } ) ;
414- } else if ( subfilter . operator === FilterOperator . NIN ) {
415- const values = Array . isArray ( subfilter . value )
416- ? subfilter . value . map ( String )
417- : String ( subfilter . value ) . split ( "," ) ;
377+ } else if ( operator === FilterOperator . LT ) {
378+ conditions . push ( { key, range : { lt : value as number } } ) ;
379+ } else if ( operator === FilterOperator . GT ) {
380+ conditions . push ( { key, range : { gt : value as number } } ) ;
381+ } else if ( operator === FilterOperator . GTE ) {
382+ conditions . push ( { key, range : { gte : value as number } } ) ;
383+ } else if ( operator === FilterOperator . LTE ) {
384+ conditions . push ( { key, range : { lte : value as number } } ) ;
385+ } else if ( operator === FilterOperator . TEXT_MATCH ) {
386+ conditions . push ( { key, match : { text : value as string } } ) ;
387+ } else if ( operator === FilterOperator . NE ) {
418388 conditions . push ( {
419- key : subfilter . key ,
420- match : { except : values } ,
389+ must_not : [
390+ { key, match : { value : value as string | number | boolean } } ,
391+ ] ,
421392 } ) ;
422- } else if ( subfilter . operator === FilterOperator . IS_EMPTY ) {
393+ } else if ( operator === FilterOperator . IN ) {
394+ const values = Array . isArray ( value ) ? value : [ value ] ;
395+ conditions . push ( { key, match : { any : values as ( string | number ) [ ] } } ) ;
396+ } else if ( operator === FilterOperator . NIN ) {
397+ const values = Array . isArray ( value ) ? value : [ value ] ;
423398 conditions . push ( {
424- is_empty : { key : subfilter . key } ,
399+ must_not : [ { key, match : { any : values as ( string | number ) [ ] } } ] ,
425400 } ) ;
401+ } else if ( operator === FilterOperator . IS_EMPTY ) {
402+ conditions . push ( { is_empty : { key } } ) ;
426403 }
427404 }
428405
0 commit comments