BinaryVectorExample.java 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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. package io.milvus.v1;
  20. import com.google.gson.Gson;
  21. import com.google.gson.JsonObject;
  22. import io.milvus.client.MilvusServiceClient;
  23. import io.milvus.common.clientenum.ConsistencyLevelEnum;
  24. import io.milvus.grpc.*;
  25. import io.milvus.param.*;
  26. import io.milvus.param.collection.*;
  27. import io.milvus.param.dml.InsertParam;
  28. import io.milvus.param.dml.QueryParam;
  29. import io.milvus.param.dml.SearchParam;
  30. import io.milvus.param.index.CreateIndexParam;
  31. import io.milvus.response.FieldDataWrapper;
  32. import io.milvus.response.QueryResultsWrapper;
  33. import io.milvus.response.SearchResultsWrapper;
  34. import java.nio.ByteBuffer;
  35. import java.util.*;
  36. public class BinaryVectorExample {
  37. private static final String COLLECTION_NAME = "java_sdk_example_binary_vector";
  38. private static final String ID_FIELD = "id";
  39. private static final String VECTOR_FIELD = "vector";
  40. private static final Integer VECTOR_DIM = 512;
  41. public static void main(String[] args) {
  42. // Connect to Milvus server. Replace the "localhost" and port with your Milvus server address.
  43. MilvusServiceClient milvusClient = new MilvusServiceClient(ConnectParam.newBuilder()
  44. .withHost("localhost")
  45. .withPort(19530)
  46. .build());
  47. // drop the collection if you don't need the collection anymore
  48. R<Boolean> hasR = milvusClient.hasCollection(HasCollectionParam.newBuilder()
  49. .withCollectionName(COLLECTION_NAME)
  50. .build());
  51. CommonUtils.handleResponseStatus(hasR);
  52. if (hasR.getData()) {
  53. milvusClient.dropCollection(DropCollectionParam.newBuilder()
  54. .withCollectionName(COLLECTION_NAME)
  55. .build());
  56. }
  57. // Define fields
  58. List<FieldType> fieldsSchema = Arrays.asList(
  59. FieldType.newBuilder()
  60. .withName(ID_FIELD)
  61. .withDataType(DataType.Int64)
  62. .withPrimaryKey(true)
  63. .withAutoID(false)
  64. .build(),
  65. FieldType.newBuilder()
  66. .withName(VECTOR_FIELD)
  67. .withDataType(DataType.BinaryVector)
  68. .withDimension(VECTOR_DIM)
  69. .build()
  70. );
  71. // Create the collection
  72. R<RpcStatus> ret = milvusClient.createCollection(CreateCollectionParam.newBuilder()
  73. .withCollectionName(COLLECTION_NAME)
  74. .withConsistencyLevel(ConsistencyLevelEnum.STRONG)
  75. .withFieldTypes(fieldsSchema)
  76. .build());
  77. CommonUtils.handleResponseStatus(ret);
  78. System.out.println("Collection created");
  79. // Insert entities by columns
  80. int rowCount = 10000;
  81. List<Long> ids = new ArrayList<>();
  82. for (long i = 0L; i < rowCount; ++i) {
  83. ids.add(i);
  84. }
  85. List<ByteBuffer> vectors = CommonUtils.generateBinaryVectors(VECTOR_DIM, rowCount);
  86. List<InsertParam.Field> fieldsInsert = new ArrayList<>();
  87. fieldsInsert.add(new InsertParam.Field(ID_FIELD, ids));
  88. fieldsInsert.add(new InsertParam.Field(VECTOR_FIELD, vectors));
  89. R<MutationResult> insertR = milvusClient.insert(InsertParam.newBuilder()
  90. .withCollectionName(COLLECTION_NAME)
  91. .withFields(fieldsInsert)
  92. .build());
  93. CommonUtils.handleResponseStatus(insertR);
  94. // Insert entities by rows
  95. List<JsonObject> rows = new ArrayList<>();
  96. Gson gson = new Gson();
  97. for (long i = 1L; i <= rowCount; ++i) {
  98. JsonObject row = new JsonObject();
  99. row.addProperty(ID_FIELD, rowCount + i);
  100. row.add(VECTOR_FIELD, gson.toJsonTree(CommonUtils.generateBinaryVector(VECTOR_DIM).array()));
  101. rows.add(row);
  102. }
  103. insertR = milvusClient.insert(InsertParam.newBuilder()
  104. .withCollectionName(COLLECTION_NAME)
  105. .withRows(rows)
  106. .build());
  107. CommonUtils.handleResponseStatus(insertR);
  108. // Flush the data to storage for testing purpose
  109. // Note that no need to manually call flush interface in practice
  110. R<FlushResponse> flushR = milvusClient.flush(FlushParam.newBuilder().
  111. addCollectionName(COLLECTION_NAME).
  112. build());
  113. CommonUtils.handleResponseStatus(flushR);
  114. System.out.println("Entities inserted");
  115. // Specify an index type on the vector field.
  116. ret = milvusClient.createIndex(CreateIndexParam.newBuilder()
  117. .withCollectionName(COLLECTION_NAME)
  118. .withFieldName(VECTOR_FIELD)
  119. .withIndexType(IndexType.BIN_IVF_FLAT)
  120. .withMetricType(MetricType.HAMMING)
  121. .withExtraParam("{\"nlist\":64}")
  122. .build());
  123. CommonUtils.handleResponseStatus(ret);
  124. System.out.println("Index created");
  125. // Call loadCollection() to enable automatically loading data into memory for searching
  126. ret = milvusClient.loadCollection(LoadCollectionParam.newBuilder()
  127. .withCollectionName(COLLECTION_NAME)
  128. .build());
  129. CommonUtils.handleResponseStatus(ret);
  130. System.out.println("Collection loaded");
  131. // Pick some vectors from the inserted vectors to search
  132. // Ensure the returned top1 item's ID should be equal to target vector's ID
  133. for (int i = 0; i < 10; i++) {
  134. Random ran = new Random();
  135. int k = ran.nextInt(rowCount);
  136. ByteBuffer targetVector = vectors.get(k);
  137. R<SearchResults> searchRet = milvusClient.search(SearchParam.newBuilder()
  138. .withCollectionName(COLLECTION_NAME)
  139. .withMetricType(MetricType.HAMMING)
  140. .withTopK(3)
  141. .withBinaryVectors(Collections.singletonList(targetVector))
  142. .withVectorFieldName(VECTOR_FIELD)
  143. .addOutField(VECTOR_FIELD)
  144. .withParams("{\"nprobe\":16}")
  145. .build());
  146. CommonUtils.handleResponseStatus(searchRet);
  147. // The search() allows multiple target vectors to search in a batch.
  148. // Here we only input one vector to search, get the result of No.0 vector to check
  149. SearchResultsWrapper resultsWrapper = new SearchResultsWrapper(searchRet.getData().getResults());
  150. List<SearchResultsWrapper.IDScore> scores = resultsWrapper.getIDScore(0);
  151. System.out.printf("The result of No.%d target vector:\n", i);
  152. for (SearchResultsWrapper.IDScore score : scores) {
  153. System.out.printf("ID: %d, Score: %f, Vector: ", score.getLongID(), score.getScore());
  154. ByteBuffer vector = (ByteBuffer)score.get(VECTOR_FIELD);
  155. vector.rewind();
  156. while (vector.hasRemaining()) {
  157. System.out.print(Integer.toBinaryString(vector.get()));
  158. }
  159. System.out.println();
  160. }
  161. if (scores.get(0).getLongID() != k) {
  162. throw new RuntimeException(String.format("The top1 ID %d is not equal to target vector's ID %d",
  163. scores.get(0).getLongID(), k));
  164. }
  165. }
  166. System.out.println("Search result is correct");
  167. // Retrieve some data
  168. int n = 99;
  169. R<QueryResults> queryR = milvusClient.query(QueryParam.newBuilder()
  170. .withCollectionName(COLLECTION_NAME)
  171. .withExpr(String.format("id == %d", n))
  172. .addOutField(VECTOR_FIELD)
  173. .build());
  174. CommonUtils.handleResponseStatus(queryR);
  175. QueryResultsWrapper queryWrapper = new QueryResultsWrapper(queryR.getData());
  176. FieldDataWrapper field = queryWrapper.getFieldWrapper(VECTOR_FIELD);
  177. List<?> r = field.getFieldData();
  178. if (r.isEmpty()) {
  179. throw new RuntimeException("The query result is empty");
  180. } else {
  181. ByteBuffer vector = (ByteBuffer) r.get(0);
  182. if (vector.compareTo(vectors.get(n)) != 0) {
  183. throw new RuntimeException("The query result is incorrect");
  184. }
  185. }
  186. System.out.println("Query result is correct");
  187. // drop the collection if you don't need the collection anymore
  188. milvusClient.dropCollection(DropCollectionParam.newBuilder()
  189. .withCollectionName(COLLECTION_NAME)
  190. .build());
  191. System.out.println("Collection dropped");
  192. milvusClient.close();
  193. }
  194. }