@@ -61,7 +61,7 @@ public class StructExample {
6161 private static final String CLIP_VECTOR_FIELD = "clip_embedding" ;
6262 private static final String DESC_FIELD = "clip_desc" ;
6363 private static final String DESC_VECTOR_FIELD = "description_embedding" ;
64- private static final Integer VECTOR_DIM = 4 ;
64+ private static final Integer VECTOR_DIM = 128 ;
6565
6666 private static void createCollection () {
6767 CreateCollectionReq .CollectionSchema collectionSchema = CreateCollectionReq .CollectionSchema .builder ()
@@ -121,16 +121,16 @@ private static void createCollection() {
121121 // struct vector uses special index/metric type
122122 List <IndexParam > indexParams = new ArrayList <>();
123123 indexParams .add (IndexParam .builder ()
124- .fieldName (CLIP_VECTOR_FIELD )
124+ .fieldName (String . format ( "%s[%s]" , STRUCT_FIELD , CLIP_VECTOR_FIELD ) )
125125 .indexName ("index_1" )
126- .indexType (IndexParam .IndexType .EMB_LIST_HNSW )
127- .metricType (IndexParam .MetricType .MAX_SIM )
126+ .indexType (IndexParam .IndexType .HNSW )
127+ .metricType (IndexParam .MetricType .MAX_SIM_L2 )
128128 .build ());
129129 indexParams .add (IndexParam .builder ()
130- .fieldName (DESC_VECTOR_FIELD )
130+ .fieldName (String . format ( "%s[%s]" , STRUCT_FIELD , DESC_VECTOR_FIELD ) )
131131 .indexName ("index_2" )
132- .indexType (IndexParam .IndexType .EMB_LIST_HNSW )
133- .metricType (IndexParam .MetricType .MAX_SIM )
132+ .indexType (IndexParam .IndexType .HNSW )
133+ .metricType (IndexParam .MetricType .MAX_SIM_IP )
134134 .build ());
135135 client .createIndex (CreateIndexReq .builder ()
136136 .collectionName (COLLECTION_NAME )
@@ -161,7 +161,7 @@ private static void insertData(int rowCount) {
161161 JsonArray structArr = new JsonArray ();
162162 for (int k = 0 ; k < 5 ; k ++) {
163163 JsonObject struct = new JsonObject ();
164- struct .addProperty (FRAME_FIELD , ran .nextInt (1000000 ));
164+ struct .addProperty (FRAME_FIELD , ran .nextInt (10000 ));
165165 struct .add (CLIP_VECTOR_FIELD , JsonUtils .toJsonTree (CommonUtils .generateFloatVector (VECTOR_DIM )));
166166 struct .addProperty (DESC_FIELD , "clip_description_" + id );
167167 struct .add (DESC_VECTOR_FIELD , JsonUtils .toJsonTree (CommonUtils .generateFloatVector (VECTOR_DIM )));
@@ -187,7 +187,7 @@ private static void insertData(int rowCount) {
187187 System .out .printf ("%d rows persisted\n " , (long )countR .getQueryResults ().get (0 ).getEntity ().get ("count(*)" ));
188188
189189 }
190- private static void query (String filter ) {
190+ private static List < QueryResp . QueryResult > query (String filter ) {
191191 System .out .println ("===================================================" );
192192 System .out .println ("Query with filter expression: " + filter );
193193 QueryResp queryResp = client .query (QueryReq .builder ()
@@ -200,29 +200,27 @@ private static void query(String filter) {
200200 for (QueryResp .QueryResult result : queryResults ) {
201201 System .out .println (result .getEntity ());
202202 }
203+ return queryResults ;
203204 }
204205
205- private static void search (String annsField , int nq , int targetVectorsPerNQ ) {
206+ private static void search (String annsField , List < BaseVector > searchData ) {
206207 System .out .println ("===================================================" );
207- String msg = String .format ("Search on field '%s' with nq=%d and vectors_per_nq=%d" , annsField , nq , targetVectorsPerNQ );
208+ String msg = String .format ("Search on field '%s' in struct '%s' with nq=%d" ,
209+ annsField , STRUCT_FIELD , searchData .size ());
208210 System .out .println (msg );
209- List <BaseVector > searchData = new ArrayList <>();
210- for (int i = 0 ; i < nq ; i ++) {
211- EmbeddingList embList = new EmbeddingList ();
212- for (int k = 0 ; k < targetVectorsPerNQ ; k ++) {
213- embList .add (new FloatVec (CommonUtils .generateFloatVector (VECTOR_DIM )));
214- }
215- searchData .add (embList );
216- }
217211
212+
213+ String annFullName = String .format ("%s[%s]" , STRUCT_FIELD , annsField );
218214 int topK = 5 ;
219215 SearchResp searchResp = client .search (SearchReq .builder ()
220216 .collectionName (COLLECTION_NAME )
221- .annsField (annsField )
217+ .annsField (annFullName )
222218 .data (searchData )
223219 .limit (topK )
224220 .consistencyLevel (ConsistencyLevel .BOUNDED )
225- .outputFields (Arrays .asList (NAME_FIELD , FRAME_FIELD , DESC_FIELD ))
221+ .outputFields (Arrays .asList (NAME_FIELD ,
222+ String .format ("%s[%s]" , STRUCT_FIELD , FRAME_FIELD ),
223+ String .format ("%s[%s]" , STRUCT_FIELD , DESC_FIELD )))
226224 .build ());
227225 List <List <SearchResp .SearchResult >> searchResults = searchResp .getSearchResults ();
228226 for (int i = 0 ; i < searchResults .size (); i ++) {
@@ -237,8 +235,22 @@ private static void search(String annsField, int nq, int targetVectorsPerNQ) {
237235 public static void main (String [] args ) {
238236 createCollection ();
239237 insertData (2000 );
240- query (ID_FIELD + " <= 5" );
241- search (CLIP_VECTOR_FIELD , 2 , 3 );
242- search (DESC_VECTOR_FIELD , 1 , 5 );
238+
239+ // fetch 2 rows
240+ List <QueryResp .QueryResult > results = query (ID_FIELD + " in [5, 8]" );
241+
242+ // use the fetched data to search struct
243+ for (QueryResp .QueryResult result : results ) {
244+ // in the insertData() method, we inserted 5 structures for each row
245+ // in query results, each struct is represented as a Map
246+ Map <String , Object > fetchedEntity = result .getEntity ();
247+ List <Map <String , Object >> structs = (List <Map <String , Object >>)fetchedEntity .get (STRUCT_FIELD );
248+ EmbeddingList embList = new EmbeddingList ();
249+ for (Map <String , Object > struct : structs ) {
250+ List <Float > vector = (List <Float >)struct .get (CLIP_VECTOR_FIELD );
251+ embList .add (new FloatVec (vector ));
252+ }
253+ search (CLIP_VECTOR_FIELD , Collections .singletonList (embList ));
254+ }
243255 }
244256}
0 commit comments