未验证 提交 edd4c403 编写于 作者: D del-zhenwu 提交者: GitHub

[skip ci] add TestSearchEntities.java (#3433)

* [skip ci] add constants.java
Signed-off-by: Nzw <zw@milvus.io>

* [skip ci] add testIndex.java
Signed-off-by: Nzw <zw@milvus.io>

* [skip ci] add TestDeleteEntities.java
Signed-off-by: Nzw <zw@milvus.io>

* update TestSearchEntities.java
Signed-off-by: Nzw <zw@milvus.io>

* [skip ci] add TestSearchEntities.java
Signed-off-by: Nzw <zw@milvus.io>
Co-authored-by: Nzw <zw@milvus.io>
上级 30ecd17c
......@@ -10,8 +10,20 @@ public final class Constants {
public static final int n_list = 128;
public static final int n_probe = 64;
public static final int nq = 5;
public static final int topk = 10;
public static final int nb = 8000;
public static final double epsilon = 0.001;
public static final String vectorType = "float";
public static final String defaultMetricType = "L2";
public static final String indexType = "IVF_SQ8";
public static final String defaultIndexType = "FLAT";
......@@ -39,4 +51,9 @@ public final class Constants {
public static final List<Map<String,Object>> defaultEntities = Utils.genDefaultEntities(dimension, nb, vectors);
public static final List<Map<String,Object>> defaultBinaryEntities = Utils.genDefaultBinaryEntities(dimension, nb, vectorsBinary);
public static final String searchParam = Utils.setSearchParam(defaultMetricType, vectors.subList(0, nq), topk, n_probe);
public static final String binarySearchParam = Utils.setBinarySearchParam(defaultBinaryMetricType, vectorsBinary.subList(0, nq), topk, n_probe);
}
......@@ -69,7 +69,7 @@ public class MainClass {
private Object[][] genCollection(boolean isBinary, boolean autoId) throws ConnectFailedException {
Object[][] collection;
String collectionName = Utils.genUniqueStr("collection");
List<Map<String, Object>> defaultFields = Utils.genDefaultFields(dimension,isBinary);
List<Map<String, Object>> defaultFields = Utils.genDefaultFields(dimension, isBinary);
String jsonParams = String.format("{\"segment_row_count\": %s, \"auto_id\": %s}",segmentRowCount, autoId);
// Generate connection instance
MilvusClient client = new MilvusGrpcClient();
......@@ -86,6 +86,7 @@ public class MainClass {
collection = new Object[][]{{client, collectionName}};
return collection;
}
@DataProvider(name="Collection")
public Object[][] provideCollection() throws ConnectFailedException, InterruptedException {
Object[][] collection = genCollection(false,true);
......
//package com;
//
//import io.milvus.client.*;
//import org.apache.commons.lang3.RandomStringUtils;
//import org.testng.Assert;
//import org.testng.annotations.Test;
//
//import java.nio.ByteBuffer;
//import java.util.*;
//import java.util.stream.Collectors;
//import java.util.stream.Stream;
//
//public class TestSearchVectors {
// int dimension = 128;
// int n_list = 1024;
// int default_n_list = 16384;
// int nb = 10000;
// int small_nb = 10;
// int n_probe = 20;
// int top_k = 10;
// int nq = 5;
// double epsilon = 0.001;
// String indexType = "IVF_SQ8";
// String defaultIndexType = "FLAT";
// List<List<Float>> vectors = Utils.genVectors(nb, dimension, true);
// List<List<Float>> small_vectors = Utils.genVectors(small_nb, dimension, true);
// List<ByteBuffer> vectorsBinary = Utils.genBinaryVectors(nb, dimension);
// List<List<Float>> queryVectors = vectors.subList(0, nq);
// List<ByteBuffer> queryVectorsBinary = vectorsBinary.subList(0, nq);
// String indexParam = Utils.setIndexParam(n_list);
// public String searchParamStr = Utils.setSearchParam(n_probe);
//
// @Test(dataProvider = "Collection", dataProviderClass = MainClass.class)
// public void test_search_collection_not_existed(MilvusClient client, String collectionName) {
// String collectionNameNew = collectionName + "_";
// SearchParam searchParam = new SearchParam.Builder(collectionNameNew)
// .withFloatVectors(queryVectors)
// .withParamsInJson(searchParamStr)
// .withTopK(top_k).build();
// SearchResponse res_search = client.search(searchParam);
// assert (!res_search.getResponse().ok());
// }
//
// @Test(dataProvider = "Collection", dataProviderClass = MainClass.class)
// public void test_search_index_IVFLAT(MilvusClient client, String collectionName) {
// IndexType indexType = IndexType.IVFLAT;
// InsertParam insertParam = new InsertParam.Builder(collectionName).withFloatVectors(vectors).build();
// client.insert(insertParam);
// client.flush(collectionName);
// Index index = new Index.Builder(collectionName, indexType).withParamsInJson(indexParam).build();
// client.createIndex(index);
// SearchParam searchParam = new SearchParam.Builder(collectionName)
// .withFloatVectors(queryVectors)
// .withParamsInJson(searchParamStr)
// .withTopK(top_k).build();
// List<List<SearchResponse.QueryResult>> res_search = client.search(searchParam).getQueryResultsList();
// Assert.assertEquals(res_search.size(), nq);
// Assert.assertEquals(res_search.get(0).size(), top_k);
// }
//
// @Test(dataProvider = "Collection", dataProviderClass = MainClass.class)
// public void test_search_ids_IVFLAT(MilvusClient client, String collectionName) {
// IndexType indexType = IndexType.IVFLAT;
// List<Long> vectorIds;
// vectorIds = Stream.iterate(0L, n -> n)
// .limit(nb)
// .collect(Collectors.toList());
// InsertParam insertParam = new InsertParam.Builder(collectionName).withFloatVectors(vectors).withVectorIds(vectorIds).build();
// InsertResponse res = client.insert(insertParam);
// Index index = new Index.Builder(collectionName, indexType).withParamsInJson(indexParam).build();
// client.createIndex(index);
// SearchParam searchParam = new SearchParam.Builder(collectionName)
// .withFloatVectors(queryVectors)
// .withParamsInJson(searchParamStr)
// .withTopK(top_k).build();
// List<List<SearchResponse.QueryResult>> res_search = client.search(searchParam).getQueryResultsList();
// Assert.assertEquals(res_search.get(0).get(0).getVectorId(), 0L);
// }
//
// @Test(dataProvider = "Collection", dataProviderClass = MainClass.class)
// public void test_search_distance_IVFLAT(MilvusClient client, String collectionName) {
// IndexType indexType = IndexType.IVFLAT;
// InsertParam insertParam = new InsertParam.Builder(collectionName).withFloatVectors(vectors).build();
// InsertResponse res = client.insert(insertParam);
// Index index = new Index.Builder(collectionName, indexType).withParamsInJson(indexParam).build();
// client.createIndex(index);
// SearchParam searchParam = new SearchParam.Builder(collectionName)
// .withFloatVectors(queryVectors)
// .withParamsInJson(searchParamStr)
// .withTopK(top_k).build();
// List<List<SearchResponse.QueryResult>> res_search = client.search(searchParam).getQueryResultsList();
// double distance = res_search.get(0).get(0).getDistance();
// if (collectionName.startsWith("L2")) {
// Assert.assertEquals(distance, 0.0, epsilon);
// }else if (collectionName.startsWith("IP")) {
// Assert.assertEquals(distance, 1.0, epsilon);
// }
// }
//
// @Test(dataProvider = "Collection", dataProviderClass = MainClass.class)
// public void test_search_partition(MilvusClient client, String collectionName) {
// IndexType indexType = IndexType.IVFLAT;
// String tag = RandomStringUtils.randomAlphabetic(10);
// Response createpResponse = client.createPartition(collectionName, tag);
// InsertParam insertParam = new InsertParam.Builder(collectionName).withFloatVectors(vectors).build();
// InsertResponse res = client.insert(insertParam);
// Index index = new Index.Builder(collectionName, indexType).withParamsInJson(indexParam).build();
// client.createIndex(index);
// SearchParam searchParam = new SearchParam.Builder(collectionName)
// .withFloatVectors(queryVectors)
// .withParamsInJson(searchParamStr)
// .withTopK(top_k).build();
// List<List<SearchResponse.QueryResult>> res_search = client.search(searchParam).getQueryResultsList();
// double distance = res_search.get(0).get(0).getDistance();
// if (collectionName.startsWith("L2")) {
// Assert.assertEquals(distance, 0.0, epsilon);
// }else if (collectionName.startsWith("IP")) {
// Assert.assertEquals(distance, 1.0, epsilon);
// }
// }
//
// @Test(dataProvider = "Collection", dataProviderClass = MainClass.class)
// public void test_search_partition_not_exited(MilvusClient client, String collectionName) {
// IndexType indexType = IndexType.IVFLAT;
// String tag = RandomStringUtils.randomAlphabetic(10);
// Response createpResponse = client.createPartition(collectionName, tag);
// InsertParam insertParam = new InsertParam.Builder(collectionName).withFloatVectors(vectors).build();
// InsertResponse res = client.insert(insertParam);
// String tagNew = RandomStringUtils.randomAlphabetic(10);
// List<String> queryTags = new ArrayList<>();
// queryTags.add(tagNew);
// SearchParam searchParam = new SearchParam.Builder(collectionName)
// .withFloatVectors(queryVectors)
// .withParamsInJson(searchParamStr)
// .withPartitionTags(queryTags)
// .withTopK(top_k).build();
// SearchResponse res_search = client.search(searchParam);
// assert (!res_search.getResponse().ok());
// Assert.assertEquals(res_search.getQueryResultsList().size(), 0);
// }
//
// @Test(dataProvider = "Collection", dataProviderClass = MainClass.class)
// public void test_search_partition_empty(MilvusClient client, String collectionName) {
// IndexType indexType = IndexType.IVFLAT;
// String tag = RandomStringUtils.randomAlphabetic(10);
// Response createpResponse = client.createPartition(collectionName, tag);
// String tagNew = "";
// List<String> queryTags = new ArrayList<>();
// queryTags.add(tagNew);
// SearchParam searchParam = new SearchParam.Builder(collectionName)
// .withFloatVectors(queryVectors)
// .withParamsInJson(searchParamStr)
// .withPartitionTags(queryTags)
// .withTopK(top_k).build();
// SearchResponse res_search = client.search(searchParam);
// assert (!res_search.getResponse().ok());
// }
//
// @Test(dataProvider = "Collection", dataProviderClass = MainClass.class)
// public void test_search_distance_FLAT(MilvusClient client, String collectionName) {
// IndexType indexType = IndexType.FLAT;
// InsertParam insertParam = new InsertParam.Builder(collectionName).withFloatVectors(vectors).build();
// InsertResponse res = client.insert(insertParam);
// Index index = new Index.Builder(collectionName, indexType).withParamsInJson(indexParam).build();
// client.createIndex(index);
// SearchParam searchParam = new SearchParam.Builder(collectionName)
// .withFloatVectors(queryVectors)
// .withParamsInJson(searchParamStr)
// .withTopK(top_k).build();
// List<List<SearchResponse.QueryResult>> res_search = client.search(searchParam).getQueryResultsList();
// double distance = res_search.get(0).get(0).getDistance();
// if (collectionName.startsWith("L2")) {
// Assert.assertEquals(distance, 0.0, epsilon);
// }else if (collectionName.startsWith("IP")) {
// Assert.assertEquals(distance, 1.0, epsilon);
// }
// }
//
// @Test(dataProvider = "Collection", dataProviderClass = MainClass.class)
// public void test_search_invalid_n_probe(MilvusClient client, String collectionName) {
// int n_probe_new = -1;
// String searchParamStrNew = Utils.setSearchParam(n_probe_new);
// InsertParam insertParam = new InsertParam.Builder(collectionName).withFloatVectors(vectors).build();
// client.insert(insertParam);
// Index index = new Index.Builder(collectionName, indexType).withParamsInJson(indexParam).build();
// client.createIndex(index);
// SearchParam searchParam = new SearchParam.Builder(collectionName)
// .withFloatVectors(queryVectors)
// .withParamsInJson(searchParamStrNew)
// .withTopK(top_k).build();
// SearchResponse res_search = client.search(searchParam);
// assert (!res_search.getResponse().ok());
// }
//
// @Test(dataProvider = "Collection", dataProviderClass = MainClass.class)
// public void test_search_count_lt_top_k(MilvusClient client, String collectionName) {
// int top_k_new = 100;
// InsertParam insertParam = new InsertParam.Builder(collectionName).withFloatVectors(small_vectors).build();
// client.insert(insertParam);
// client.flush(collectionName);
// SearchParam searchParam = new SearchParam.Builder(collectionName)
// .withFloatVectors(queryVectors)
// .withParamsInJson(searchParamStr)
// .withTopK(top_k_new).build();
// List<List<SearchResponse.QueryResult>> res_search = client.search(searchParam).getQueryResultsList();
// Assert.assertEquals(res_search.size(), nq);
// Assert.assertEquals(res_search.get(0).size(), small_vectors.size());
// }
//
// @Test(dataProvider = "Collection", dataProviderClass = MainClass.class)
// public void test_search_invalid_top_k(MilvusClient client, String collectionName) {
// int top_k_new = 0;
// InsertParam insertParam = new InsertParam.Builder(collectionName).withFloatVectors(vectors).build();
// client.insert(insertParam);
// SearchParam searchParam = new SearchParam.Builder(collectionName)
// .withFloatVectors(queryVectors)
// .withParamsInJson(searchParamStr)
// .withTopK(top_k_new).build();
// SearchResponse res_search = client.search(searchParam);
// assert (!res_search.getResponse().ok());
// }
//
package com;
import io.milvus.client.*;
import org.apache.commons.lang3.RandomStringUtils;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.nio.ByteBuffer;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class TestSearchEntities {
int small_nb = 10;
int n_probe = 20;
int top_k = 10;
int nq = 5;
List<List<Float>> queryVectors = Constants.vectors.subList(0, nq);
List<ByteBuffer> queryVectorsBinary = Constants.vectorsBinary.subList(0, nq);
public String dsl = Constants.searchParam;
@Test(dataProvider = "Collection", dataProviderClass = MainClass.class)
public void testSearchCollectionNotExisted(MilvusClient client, String collectionName) {
String collectionNameNew = Utils.genUniqueStr(collectionName);
SearchParam searchParam = new SearchParam.Builder(collectionNameNew).withDSL(dsl).build();
SearchResponse res_search = client.search(searchParam);
assert (!res_search.getResponse().ok());
}
@Test(dataProvider = "Collection", dataProviderClass = MainClass.class)
public void testSearchCollectionEmpty(MilvusClient client, String collectionName) {
SearchParam searchParam = new SearchParam.Builder(collectionName).withDSL(dsl).build();
SearchResponse res_search = client.search(searchParam);
assert (res_search.getResponse().ok());
Assert.assertEquals(res_search.getResultIdsList().size(), 0);
}
// # 3429
@Test(dataProvider = "Collection", dataProviderClass = MainClass.class)
public void testSearchCollection(MilvusClient client, String collectionName) {
InsertParam insertParam = new InsertParam.Builder(collectionName).withFields(Constants.defaultEntities).build();
InsertResponse res = client.insert(insertParam);
assert(res.getResponse().ok());
List<Long> ids = res.getEntityIds();
client.flush(collectionName);
SearchParam searchParam = new SearchParam.Builder(collectionName).withDSL(dsl).build();
SearchResponse res_search = client.search(searchParam);
Assert.assertEquals(res_search.getResultIdsList().size(), Constants.nq);
Assert.assertEquals(res_search.getResultDistancesList().size(), Constants.nq);
Assert.assertEquals(res_search.getResultIdsList().get(0).size(), Constants.topk);
Assert.assertEquals(res_search.getResultIdsList().get(0).get(0), ids.get(0));
Assert.assertEquals(res_search.getFieldsMap().get(0).size(), top_k);
}
@Test(dataProvider = "Collection", dataProviderClass = MainClass.class)
public void testSearchDistance(MilvusClient client, String collectionName) {
InsertParam insertParam = new InsertParam.Builder(collectionName).withFields(Constants.defaultEntities).build();
InsertResponse res = client.insert(insertParam);
assert(res.getResponse().ok());
List<Long> ids = res.getEntityIds();
client.flush(collectionName);
SearchParam searchParam = new SearchParam.Builder(collectionName).withDSL(dsl).build();
SearchResponse res_search = client.search(searchParam);
for (int i = 0; i < Constants.nq; i++) {
double distance = res_search.getResultDistancesList().get(i).get(0);
Assert.assertEquals(distance, 0.0, Constants.epsilon);
}
}
@Test(dataProvider = "Collection", dataProviderClass = MainClass.class)
public void testSearchDistanceIP(MilvusClient client, String collectionName) {
InsertParam insertParam = new InsertParam.Builder(collectionName).withFields(Constants.defaultEntities).build();
InsertResponse res = client.insert(insertParam);
assert(res.getResponse().ok());
List<Long> ids = res.getEntityIds();
client.flush(collectionName);
String dsl = Utils.setSearchParam("IP", Constants.vectors.subList(0, nq), top_k, n_probe);
SearchParam searchParam = new SearchParam.Builder(collectionName).withDSL(dsl).build();
SearchResponse res_search = client.search(searchParam);
for (int i = 0; i < Constants.nq; i++) {
double distance = res_search.getResultDistancesList().get(i).get(0);
Assert.assertEquals(distance, 1.0, Constants.epsilon);
}
}
@Test(dataProvider = "Collection", dataProviderClass = MainClass.class)
public void testSearchPartition(MilvusClient client, String collectionName) {
String tag = "tag";
List<String> queryTags = new ArrayList<>();
queryTags.add(tag);
client.createPartition(collectionName, tag);
InsertParam insertParam = new InsertParam.Builder(collectionName).withFields(Constants.defaultEntities).build();
InsertResponse res = client.insert(insertParam);
assert(res.getResponse().ok());
client.flush(collectionName);
SearchParam searchParam = new SearchParam.Builder(collectionName).withDSL(dsl).withPartitionTags(queryTags).build();
SearchResponse res_search = client.search(searchParam);
Assert.assertEquals(res_search.getResultDistancesList().size(), 0);
}
@Test(dataProvider = "Collection", dataProviderClass = MainClass.class)
public void testSearchPartitionNotExited(MilvusClient client, String collectionName) {
String tag = Utils.genUniqueStr("tag");
List<String> queryTags = new ArrayList<>();
queryTags.add(tag);
client.createPartition(collectionName, tag);
InsertParam insertParam = new InsertParam.Builder(collectionName).withFields(Constants.defaultEntities).build();
InsertResponse res = client.insert(insertParam);
assert (res.getResponse().ok());
client.flush(collectionName);
SearchParam searchParam = new SearchParam.Builder(collectionName).withDSL(dsl).withPartitionTags(queryTags).build();
SearchResponse res_search = client.search(searchParam);
Assert.assertEquals(res_search.getResultDistancesList().size(), 0);
}
@Test(dataProvider = "Collection", dataProviderClass = MainClass.class)
public void testSearchInvalidNProbe(MilvusClient client, String collectionName) {
int n_probe_new = -1;
InsertParam insertParam = new InsertParam.Builder(collectionName).withFields(Constants.defaultEntities).build();
InsertResponse res = client.insert(insertParam);
assert(res.getResponse().ok());
List<Long> ids = res.getEntityIds();
client.flush(collectionName);
Index index = new Index.Builder(collectionName, Constants.floatFieldName).withParamsInJson(Constants.indexParam).build();
Response res_create = client.createIndex(index);
String dsl = Utils.setSearchParam(Constants.defaultMetricType, Constants.vectors.subList(0, nq), top_k, n_probe_new);
SearchParam searchParam = new SearchParam.Builder(collectionName).withDSL(dsl).build();
SearchResponse res_search = client.search(searchParam);
assert(!res_search.getResponse().ok());
}
@Test(dataProvider = "Collection", dataProviderClass = MainClass.class)
public void testSearchCountLessThanTopK(MilvusClient client, String collectionName) {
int top_k_new = 100;
int nb = 50;
List<Map<String,Object>> entities = Utils.genDefaultEntities(Constants.dimension, nb, Utils.genVectors(nb, Constants.dimension, false));
InsertParam insertParam = new InsertParam.Builder(collectionName).withFields(entities).build();
InsertResponse res = client.insert(insertParam);
assert(res.getResponse().ok());
List<Long> ids = res.getEntityIds();
client.flush(collectionName);
String dsl = Utils.setSearchParam(Constants.defaultMetricType, Constants.vectors.subList(0, nq), top_k_new, n_probe);
SearchParam searchParam = new SearchParam.Builder(collectionName).withDSL(dsl).build();
SearchResponse res_search = client.search(searchParam);
assert(res_search.getResponse().ok());
Assert.assertEquals(res_search.getResultIdsList().size(), Constants.nq);
Assert.assertEquals(res_search.getResultDistancesList().size(), Constants.nq);
Assert.assertEquals(res_search.getResultIdsList().get(0).size(), nb);
}
@Test(dataProvider = "Collection", dataProviderClass = MainClass.class)
public void testSearchInvalidTopK(MilvusClient client, String collectionName) {
int top_k = -1;
InsertParam insertParam = new InsertParam.Builder(collectionName).withFields(Constants.defaultEntities).build();
InsertResponse res = client.insert(insertParam);
assert(res.getResponse().ok());
List<Long> ids = res.getEntityIds();
client.flush(collectionName);
// Index index = new Index.Builder(collectionName, Constants.floatFieldName).withParamsInJson(Constants.indexParam).build();
// Response res_create = client.createIndex(index);
String dsl = Utils.setSearchParam(Constants.defaultMetricType, Constants.vectors.subList(0, nq), top_k, n_probe);
SearchParam searchParam = new SearchParam.Builder(collectionName).withDSL(dsl).build();
SearchResponse res_search = client.search(searchParam);
assert(!res_search.getResponse().ok());
}
// // Binary tests
// @Test(dataProvider = "BinaryCollection", dataProviderClass = MainClass.class)
// public void test_search_collection_not_existed_binary(MilvusClient client, String collectionName) {
// String collectionNameNew = collectionName + "_";
// public void testSearchCollectionNotExistedBinary(MilvusClient client, String collectionName) {
// String collectionNameNew = Utils.genUniqueStr(collectionName);
// SearchParam searchParam = new SearchParam.Builder(collectionNameNew)
// .withBinaryVectors(queryVectorsBinary)
// .withParamsInJson(searchParamStr)
......@@ -314,5 +260,5 @@
// SearchResponse res_search = client.search(searchParam);
// assert (!res_search.getResponse().ok());
// }
//
//}
}
package com;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import io.milvus.client.*;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.RandomStringUtils;
......@@ -146,9 +148,44 @@ public class Utils {
return indexParams;
}
public static String setSearchParam(int nprobe) {
public static String setSearchParam(String metricType, List<List<Float>> queryVectors, int topk, int nprobe) {
JSONObject searchParam = new JSONObject();
searchParam.put("nprobe", nprobe);
JSONObject fieldParam = new JSONObject();
fieldParam.put("topk", topk);
fieldParam.put("metric_type", metricType);
fieldParam.put("query", queryVectors);
fieldParam.put("type", Constants.vectorType);
JSONObject tmpSearchParam = new JSONObject();
tmpSearchParam.put("nprobe", nprobe);
fieldParam.put("params", tmpSearchParam);
JSONObject vectorParams = new JSONObject();
vectorParams.put(Constants.floatFieldName, fieldParam);
searchParam.put("vector", vectorParams);
JSONObject param = new JSONObject();
JSONObject mustParam = new JSONObject();
JSONArray tmp = new JSONArray();
tmp.add(searchParam);
mustParam.put("must", tmp);
param.put("bool", mustParam);
return JSONObject.toJSONString(param);
}
public static String setBinarySearchParam(String metricType, List<ByteBuffer> queryVectors, int topk, int nprobe) {
JSONObject searchParam = new JSONObject();
JSONObject fieldParam = new JSONObject();
fieldParam.put("topk", topk);
fieldParam.put("metricType", metricType);
fieldParam.put("queryVectors", queryVectors);
JSONObject tmpSearchParam = new JSONObject();
tmpSearchParam.put("nprobe", nprobe);
fieldParam.put("params", tmpSearchParam);
JSONObject vectorParams = new JSONObject();
vectorParams.put(Constants.floatFieldName, fieldParam);
searchParam.put("vector", vectorParams);
JSONObject boolParam = new JSONObject();
JSONObject mustParam = new JSONObject();
mustParam.put("must", new JSONArray().add(searchParam));
boolParam.put("bool", mustParam);
return JSONObject.toJSONString(searchParam);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册