Skip to content

Commit c4029da

Browse files
authored
Add example for struct field (#1622)
Signed-off-by: yhmo <yihua.mo@zilliz.com>
1 parent d194d7c commit c4029da

File tree

2 files changed

+244
-1
lines changed

2 files changed

+244
-1
lines changed
Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package io.milvus.v2;
21+
22+
import com.google.gson.JsonArray;
23+
import com.google.gson.JsonObject;
24+
import io.milvus.common.utils.JsonUtils;
25+
import io.milvus.v1.CommonUtils;
26+
import io.milvus.v2.client.ConnectConfig;
27+
import io.milvus.v2.client.MilvusClientV2;
28+
import io.milvus.v2.common.ConsistencyLevel;
29+
import io.milvus.v2.common.DataType;
30+
import io.milvus.v2.common.IndexParam;
31+
import io.milvus.v2.service.collection.request.AddFieldReq;
32+
import io.milvus.v2.service.collection.request.CreateCollectionReq;
33+
import io.milvus.v2.service.collection.request.DropCollectionReq;
34+
import io.milvus.v2.service.collection.request.LoadCollectionReq;
35+
import io.milvus.v2.service.index.request.CreateIndexReq;
36+
import io.milvus.v2.service.vector.request.InsertReq;
37+
import io.milvus.v2.service.vector.request.QueryReq;
38+
import io.milvus.v2.service.vector.request.SearchReq;
39+
import io.milvus.v2.service.vector.request.data.BaseVector;
40+
import io.milvus.v2.service.vector.request.data.EmbeddingList;
41+
import io.milvus.v2.service.vector.request.data.FloatVec;
42+
import io.milvus.v2.service.vector.response.InsertResp;
43+
import io.milvus.v2.service.vector.response.QueryResp;
44+
import io.milvus.v2.service.vector.response.SearchResp;
45+
46+
import java.util.*;
47+
48+
public class StructExample {
49+
private static final MilvusClientV2 client;
50+
static {
51+
client = new MilvusClientV2(ConnectConfig.builder()
52+
.uri("http://localhost:19530")
53+
.build());
54+
}
55+
56+
private static final String COLLECTION_NAME = "java_sdk_example_struct_v2";
57+
private static final String ID_FIELD = "id";
58+
private static final String NAME_FIELD = "film_name";
59+
private static final String STRUCT_FIELD = "clips";
60+
private static final String FRAME_FIELD = "frame_number";
61+
private static final String CLIP_VECTOR_FIELD = "clip_embedding";
62+
private static final String DESC_FIELD = "clip_desc";
63+
private static final String DESC_VECTOR_FIELD = "description_embedding";
64+
private static final Integer VECTOR_DIM = 4;
65+
66+
private static void createCollection() {
67+
CreateCollectionReq.CollectionSchema collectionSchema = CreateCollectionReq.CollectionSchema.builder()
68+
.build();
69+
collectionSchema.addField(AddFieldReq.builder()
70+
.fieldName(ID_FIELD)
71+
.dataType(DataType.Int64)
72+
.isPrimaryKey(true)
73+
.build());
74+
collectionSchema.addField(AddFieldReq.builder()
75+
.fieldName(NAME_FIELD)
76+
.dataType(DataType.VarChar)
77+
.maxLength(1024)
78+
.build());
79+
// define struct field schema, note that each name of sub-field must be unique in the entire collection
80+
collectionSchema.addField(AddFieldReq.builder()
81+
.fieldName(STRUCT_FIELD)
82+
.description("clips of a film")
83+
.dataType(DataType.Array)
84+
.elementType(DataType.Struct)
85+
.maxCapacity(100)
86+
.addStructField(AddFieldReq.builder()
87+
.fieldName(FRAME_FIELD)
88+
.description("from which frame this clip begin")
89+
.dataType(DataType.Int32)
90+
.build())
91+
.addStructField(AddFieldReq.builder()
92+
.fieldName(CLIP_VECTOR_FIELD)
93+
.description("embedding of a clip")
94+
.dataType(DataType.FloatVector)
95+
.dimension(VECTOR_DIM)
96+
.build())
97+
.addStructField(AddFieldReq.builder()
98+
.fieldName(DESC_FIELD)
99+
.description("description of a clip")
100+
.dataType(DataType.VarChar)
101+
.maxLength(1024)
102+
.build())
103+
.addStructField(AddFieldReq.builder()
104+
.fieldName(DESC_VECTOR_FIELD)
105+
.description("embedding of description")
106+
.dataType(DataType.FloatVector)
107+
.dimension(VECTOR_DIM)
108+
.build())
109+
.build());
110+
111+
client.dropCollection(DropCollectionReq.builder()
112+
.collectionName(COLLECTION_NAME)
113+
.build());
114+
115+
CreateCollectionReq requestCreate = CreateCollectionReq.builder()
116+
.collectionName(COLLECTION_NAME)
117+
.collectionSchema(collectionSchema)
118+
.build();
119+
client.createCollection(requestCreate);
120+
121+
// struct vector uses special index/metric type
122+
List<IndexParam> indexParams = new ArrayList<>();
123+
indexParams.add(IndexParam.builder()
124+
.fieldName(CLIP_VECTOR_FIELD)
125+
.indexName("index_1")
126+
.indexType(IndexParam.IndexType.EMB_LIST_HNSW)
127+
.metricType(IndexParam.MetricType.MAX_SIM)
128+
.build());
129+
indexParams.add(IndexParam.builder()
130+
.fieldName(DESC_VECTOR_FIELD)
131+
.indexName("index_2")
132+
.indexType(IndexParam.IndexType.EMB_LIST_HNSW)
133+
.metricType(IndexParam.MetricType.MAX_SIM)
134+
.build());
135+
client.createIndex(CreateIndexReq.builder()
136+
.collectionName(COLLECTION_NAME)
137+
.indexParams(indexParams)
138+
.build());
139+
client.loadCollection(LoadCollectionReq.builder()
140+
.collectionName(COLLECTION_NAME)
141+
.build());
142+
System.out.println("Collection created: " + COLLECTION_NAME);
143+
}
144+
145+
private static void insertData(int rowCount) {
146+
final int batchSize = 300;
147+
int insertedCount = 0;
148+
Random ran = new Random();
149+
while (insertedCount < rowCount) {
150+
int nextBatch = batchSize;
151+
int leftCount = rowCount - insertedCount;
152+
if (nextBatch > leftCount) {
153+
nextBatch = leftCount;
154+
}
155+
List<JsonObject> rows = new ArrayList<>();
156+
for (int i = 0; i < nextBatch; i++) {
157+
JsonObject row = new JsonObject();
158+
int id = insertedCount + i;
159+
row.addProperty(ID_FIELD, id);
160+
row.addProperty(NAME_FIELD, "film_" + id);
161+
JsonArray structArr = new JsonArray();
162+
for (int k = 0; k < 5; k++) {
163+
JsonObject struct = new JsonObject();
164+
struct.addProperty(FRAME_FIELD, ran.nextInt(1000000));
165+
struct.add(CLIP_VECTOR_FIELD, JsonUtils.toJsonTree(CommonUtils.generateFloatVector(VECTOR_DIM)));
166+
struct.addProperty(DESC_FIELD, "clip_description_" + id);
167+
struct.add(DESC_VECTOR_FIELD, JsonUtils.toJsonTree(CommonUtils.generateFloatVector(VECTOR_DIM)));
168+
structArr.add(struct);
169+
}
170+
row.add(STRUCT_FIELD, structArr);
171+
rows.add(row);
172+
}
173+
174+
InsertResp insertResp = client.insert(InsertReq.builder()
175+
.collectionName(COLLECTION_NAME)
176+
.data(rows)
177+
.build());
178+
insertedCount += (int) insertResp.getInsertCnt();
179+
System.out.println("Inserted row count: " + insertResp.getInsertCnt());
180+
}
181+
182+
QueryResp countR = client.query(QueryReq.builder()
183+
.collectionName(COLLECTION_NAME)
184+
.outputFields(Collections.singletonList("count(*)"))
185+
.consistencyLevel(ConsistencyLevel.STRONG)
186+
.build());
187+
System.out.printf("%d rows persisted\n", (long)countR.getQueryResults().get(0).getEntity().get("count(*)"));
188+
189+
}
190+
private static void query(String filter) {
191+
System.out.println("===================================================");
192+
System.out.println("Query with filter expression: " + filter);
193+
QueryResp queryResp = client.query(QueryReq.builder()
194+
.collectionName(COLLECTION_NAME)
195+
.filter(filter)
196+
.consistencyLevel(ConsistencyLevel.BOUNDED)
197+
.outputFields(Collections.singletonList(STRUCT_FIELD))
198+
.build());
199+
List<QueryResp.QueryResult> queryResults = queryResp.getQueryResults();
200+
for (QueryResp.QueryResult result : queryResults) {
201+
System.out.println(result.getEntity());
202+
}
203+
}
204+
205+
private static void search(String annsField, int nq, int targetVectorsPerNQ) {
206+
System.out.println("===================================================");
207+
String msg = String.format("Search on field '%s' with nq=%d and vectors_per_nq=%d", annsField, nq, targetVectorsPerNQ);
208+
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+
}
217+
218+
int topK = 5;
219+
SearchResp searchResp = client.search(SearchReq.builder()
220+
.collectionName(COLLECTION_NAME)
221+
.annsField(annsField)
222+
.data(searchData)
223+
.limit(topK)
224+
.consistencyLevel(ConsistencyLevel.BOUNDED)
225+
.outputFields(Arrays.asList(NAME_FIELD, FRAME_FIELD, DESC_FIELD))
226+
.build());
227+
List<List<SearchResp.SearchResult>> searchResults = searchResp.getSearchResults();
228+
for (int i = 0; i < searchResults.size(); i++) {
229+
System.out.println("Results of No." + i + " embedding list");
230+
List<SearchResp.SearchResult> results = searchResults.get(i);
231+
for (SearchResp.SearchResult result : results) {
232+
System.out.println(result);
233+
}
234+
}
235+
}
236+
237+
public static void main(String[] args) {
238+
createCollection();
239+
insertData(2000);
240+
query(ID_FIELD + " <= 5");
241+
search(CLIP_VECTOR_FIELD, 2, 3);
242+
search(DESC_VECTOR_FIELD, 1, 5);
243+
}
244+
}

sdk-core/src/test/java/io/milvus/v2/client/MilvusClientV2DockerTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1132,7 +1132,6 @@ void testStruct() {
11321132
Assertions.assertEquals(IndexParam.MetricType.MAX_SIM, desc.getMetricType());
11331133

11341134
// insert
1135-
Random RANDOM = new Random();
11361135
List<JsonObject> rows = new ArrayList<>();
11371136
int count = 20;
11381137
for (int i = 0; i < count; i++) {

0 commit comments

Comments
 (0)