2424import com .google .gson .JsonObject ;
2525import io .milvus .orm .iterator .QueryIterator ;
2626import io .milvus .orm .iterator .SearchIterator ;
27+ import io .milvus .orm .iterator .SearchIteratorV2 ;
2728import io .milvus .response .QueryResultsWrapper ;
2829import io .milvus .v1 .CommonUtils ;
2930import io .milvus .v2 .client .ConnectConfig ;
3435import io .milvus .v2 .service .collection .request .AddFieldReq ;
3536import io .milvus .v2 .service .collection .request .CreateCollectionReq ;
3637import io .milvus .v2 .service .collection .request .DropCollectionReq ;
37- import io .milvus .v2 .service .vector .request .InsertReq ;
38- import io .milvus .v2 .service .vector .request .QueryIteratorReq ;
39- import io .milvus .v2 .service .vector .request .QueryReq ;
40- import io .milvus .v2 .service .vector .request .SearchIteratorReq ;
38+ import io .milvus .v2 .service .vector .request .*;
4139import io .milvus .v2 .service .vector .request .data .FloatVec ;
4240import io .milvus .v2 .service .vector .response .InsertResp ;
4341import io .milvus .v2 .service .vector .response .QueryResp ;
42+ import io .milvus .v2 .service .vector .response .SearchResp ;
43+ import org .apache .commons .lang3 .StringUtils ;
4444
4545import java .util .*;
4646
4747public class IteratorExample {
48+ private static final MilvusClientV2 client ;
49+ static {
50+ client = new MilvusClientV2 (ConnectConfig .builder ()
51+ .uri ("http://localhost:19530" )
52+ .build ());
53+ }
4854 private static final String COLLECTION_NAME = "java_sdk_example_iterator_v2" ;
4955 private static final String ID_FIELD = "userID" ;
5056 private static final String AGE_FIELD = "userAge" ;
5157 private static final String VECTOR_FIELD = "userFace" ;
5258 private static final Integer VECTOR_DIM = 128 ;
5359
54- public static void main (String [] args ) {
55- ConnectConfig config = ConnectConfig .builder ()
56- .uri ("http://localhost:19530" )
57- .build ();
58- MilvusClientV2 client = new MilvusClientV2 (config );
59-
60+ private static void buildCollection () {
6061 // Create collection
6162 CreateCollectionReq .CollectionSchema collectionSchema = CreateCollectionReq .CollectionSchema .builder ()
6263 .build ();
@@ -123,21 +124,58 @@ public static void main(String[] args) {
123124 .build ());
124125 List <QueryResp .QueryResult > queryResults = queryResp .getQueryResults ();
125126 System .out .printf ("Inserted row count: %d\n " , queryResults .get (0 ).getEntity ().get ("count(*)" ));
127+ }
126128
127- // Search iterator
129+ // Query iterator
130+ private static void queryIterator (String expr , int batchSize , int offset , int limit ) {
131+ System .out .println ("\n ========== queryIterator() ==========" );
132+ System .out .println (String .format ("expr='%s', batchSize=%d, offset=%d, limit=%d" , expr , batchSize , offset , limit ));
133+ QueryIterator queryIterator = client .queryIterator (QueryIteratorReq .builder ()
134+ .collectionName (COLLECTION_NAME )
135+ .expr (expr )
136+ .outputFields (Lists .newArrayList (ID_FIELD , AGE_FIELD ))
137+ .batchSize (batchSize )
138+ .offset (offset )
139+ .limit (limit )
140+ .consistencyLevel (ConsistencyLevel .BOUNDED )
141+ .build ());
142+
143+ System .out .println ("QueryIterator results:" );
144+ int counter = 0 ;
145+ while (true ) {
146+ List <QueryResultsWrapper .RowRecord > res = queryIterator .next ();
147+ if (res .isEmpty ()) {
148+ System .out .println ("query iteration finished, close" );
149+ queryIterator .close ();
150+ break ;
151+ }
152+
153+ for (QueryResultsWrapper .RowRecord record : res ) {
154+ System .out .println (record );
155+ counter ++;
156+ }
157+ }
158+ System .out .printf ("%d query results returned%n" , counter );
159+ }
160+
161+ // Search iterator V1
162+ private static void searchIteratorV1 (String expr , String params , int batchSize , int topK ) {
163+ System .out .println ("\n ========== searchIteratorV1() ==========" );
164+ System .out .println (String .format ("expr='%s', params='%s', batchSize=%d, topK=%d" , expr , params , batchSize , topK ));
128165 SearchIterator searchIterator = client .searchIterator (SearchIteratorReq .builder ()
129166 .collectionName (COLLECTION_NAME )
130167 .outputFields (Lists .newArrayList (AGE_FIELD ))
131- .batchSize (50L )
168+ .batchSize (batchSize )
132169 .vectorFieldName (VECTOR_FIELD )
133170 .vectors (Collections .singletonList (new FloatVec (CommonUtils .generateFloatVector (VECTOR_DIM ))))
134- .expr (String . format ( "%s > 50 && %s < 100" , AGE_FIELD , AGE_FIELD ) )
135- .params ("{ \" range_filter \" : 15.0, \" radius \" : 20.0}" )
136- .topK (300 )
171+ .expr (expr )
172+ .params (StringUtils . isEmpty ( params ) ? "{}" : params )
173+ .topK (topK )
137174 .metricType (IndexParam .MetricType .L2 )
138175 .consistencyLevel (ConsistencyLevel .BOUNDED )
139176 .build ());
140177
178+ System .out .println ("SearchIteratorV1 results:" );
141179 int counter = 0 ;
142180 while (true ) {
143181 List <QueryResultsWrapper .RowRecord > res = searchIterator .next ();
@@ -153,34 +191,55 @@ public static void main(String[] args) {
153191 }
154192 }
155193 System .out .printf ("%d search results returned\n %n" , counter );
194+ }
156195
157- // Query iterator
158- QueryIterator queryIterator = client .queryIterator (QueryIteratorReq .builder ()
196+ // Search iterator V2
197+ // In SDK v2.5.6, we provide a new search iterator implementation. SearchIteratorV2 is recommended.
198+ // SearchIteratorV2 is faster than V1 by 20~30 percent, and the recall is a little better than V1.
199+ private static void searchIteratorV2 (String filter , Map <String , Object > params , int batchSize , int topK ) {
200+ System .out .println ("\n ========== searchIteratorV2() ==========" );
201+ System .out .println (String .format ("expr='%s', params='%s', batchSize=%d, topK=%d" ,
202+ filter , params ==null ? "" : params .toString (), batchSize , topK ));
203+ SearchIteratorV2 searchIterator = client .searchIteratorV2 (SearchIteratorReqV2 .builder ()
159204 .collectionName (COLLECTION_NAME )
160- .expr (String .format ("%s < 300" , ID_FIELD ))
161- .outputFields (Lists .newArrayList (ID_FIELD , AGE_FIELD ))
162- .batchSize (50L )
163- .offset (5 )
164- .limit (400 )
205+ .outputFields (Lists .newArrayList (AGE_FIELD ))
206+ .batchSize (batchSize )
207+ .vectorFieldName (VECTOR_FIELD )
208+ .vectors (Collections .singletonList (new FloatVec (CommonUtils .generateFloatVector (VECTOR_DIM ))))
209+ .filter (filter )
210+ .searchParams (params ==null ? new HashMap <>() : params )
211+ .topK (topK )
212+ .metricType (IndexParam .MetricType .L2 )
165213 .consistencyLevel (ConsistencyLevel .BOUNDED )
166214 .build ());
167215
168- counter = 0 ;
216+ System .out .println ("SearchIteratorV2 results:" );
217+ int counter = 0 ;
169218 while (true ) {
170- List <QueryResultsWrapper . RowRecord > res = queryIterator .next ();
219+ List <SearchResp . SearchResult > res = searchIterator .next ();
171220 if (res .isEmpty ()) {
172- System .out .println ("query iteration finished, close" );
173- queryIterator .close ();
221+ System .out .println ("Search iteration finished, close" );
222+ searchIterator .close ();
174223 break ;
175224 }
176225
177- for (QueryResultsWrapper . RowRecord record : res ) {
226+ for (SearchResp . SearchResult record : res ) {
178227 System .out .println (record );
179228 counter ++;
180229 }
181230 }
182- System .out .printf ("%d query results returned%n" , counter );
231+ System .out .printf ("%d search results returned\n %n" , counter );
232+ }
183233
184- client .close ();
234+ public static void main (String [] args ) {
235+ buildCollection ();
236+ queryIterator ("userID < 300" ,50 , 5 ,400 );
237+ searchIteratorV1 ("userAge > 50 &&userAge < 100" , "{\" range_filter\" : 15.0, \" radius\" : 20.0}" , 100 , 500 );
238+ searchIteratorV1 ("" , "" , 10 , 99 );
239+ searchIteratorV2 ("userAge > 10 &&userAge < 20" , null , 50 , 100 );
240+
241+ Map <String ,Object > extraParams = new HashMap <>();
242+ extraParams .put ("radius" ,15.0 );
243+ searchIteratorV2 ("" , extraParams , 50 , 100 );
185244 }
186245}
0 commit comments