Skip to content

Commit 4ad9742

Browse files
authored
Support aggregation for search() (#1936) (#1938)
Signed-off-by: yhmo <yihua.mo@zilliz.com>
1 parent 9b90f70 commit 4ad9742

18 files changed

Lines changed: 1965 additions & 1 deletion

File tree

examples/src/main/java/io/milvus/v2/SearchAggregationExample.java

Lines changed: 508 additions & 0 deletions
Large diffs are not rendered by default.

sdk-core/src/main/java/io/milvus/v2/client/MilvusClientV2Session.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ private SearchReq copy(SearchReq request) {
120120
.functionScore(request.getFunctionScore())
121121
.filterTemplateValues(request.getFilterTemplateValues())
122122
.highlighter(request.getHighlighter())
123+
.searchAggregation(request.getSearchAggregation())
123124
.build();
124125
}
125126

sdk-core/src/main/java/io/milvus/v2/service/vector/VectorService.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ public SearchResp search(MilvusServiceGrpc.MilvusServiceBlockingStub blockingStu
268268

269269
SearchResp.SearchRespBuilder respBuilder = SearchResp.builder()
270270
.searchResults(convertUtils.getEntities(response))
271+
.aggregationBuckets(convertUtils.getAggregationBuckets(response))
271272
.sessionTs(response.getSessionTs())
272273
.recalls(response.getResults().getRecallsList());
273274
fillSearchRespFromExtraInfo(respBuilder, response.getStatus().getExtraInfoMap());

sdk-core/src/main/java/io/milvus/v2/service/vector/request/SearchReq.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import io.milvus.v2.common.ConsistencyLevel;
2323
import io.milvus.v2.common.IndexParam;
2424
import io.milvus.v2.service.collection.request.CreateCollectionReq;
25+
import io.milvus.v2.service.vector.request.aggregation.SearchAggregation;
2526
import io.milvus.v2.service.vector.request.data.BaseVector;
2627
import io.milvus.v2.service.vector.request.highlighter.Highlighter;
2728

@@ -74,6 +75,8 @@ public class SearchReq {
7475
// milvus v2.6.9 supports highlighter for search results
7576
private Highlighter highlighter;
7677

78+
private SearchAggregation searchAggregation;
79+
7780
private SearchReq(SearchReqBuilder builder) {
7881
this.databaseName = builder.databaseName;
7982
this.collectionName = builder.collectionName;
@@ -102,6 +105,7 @@ private SearchReq(SearchReqBuilder builder) {
102105
this.filterTemplateValues = builder.filterTemplateValues;
103106
this.timezone = builder.timezone;
104107
this.highlighter = builder.highlighter;
108+
this.searchAggregation = builder.searchAggregation;
105109
}
106110

107111
// Getters and Setters
@@ -313,6 +317,14 @@ public Highlighter getHighlighter() {
313317
return highlighter;
314318
}
315319

320+
public SearchAggregation getSearchAggregation() {
321+
return searchAggregation;
322+
}
323+
324+
public void setSearchAggregation(SearchAggregation searchAggregation) {
325+
this.searchAggregation = searchAggregation;
326+
}
327+
316328
@Override
317329
public String toString() {
318330
return "SearchReq{" +
@@ -340,6 +352,7 @@ public String toString() {
340352
", strictGroupSize=" + strictGroupSize +
341353
", ranker=" + ranker +
342354
", highlighter=" + (highlighter == null ? "null" : (highlighter.highlightType() + ":" + highlighter.getParams())) +
355+
", searchAggregation=" + searchAggregation +
343356
", functionScore=" + functionScore +
344357
// ", filterTemplateValues=" + filterTemplateValues +
345358
'}';
@@ -377,6 +390,7 @@ public static class SearchReqBuilder {
377390
private FunctionScore functionScore;
378391
private Map<String, Object> filterTemplateValues = new HashMap<>(); // default value
379392
private Highlighter highlighter;
393+
private SearchAggregation searchAggregation;
380394

381395
private SearchReqBuilder() {
382396
}
@@ -520,6 +534,11 @@ public SearchReqBuilder highlighter(Highlighter highlighter) {
520534
return this;
521535
}
522536

537+
public SearchReqBuilder searchAggregation(SearchAggregation searchAggregation) {
538+
this.searchAggregation = searchAggregation;
539+
return this;
540+
}
541+
523542
public SearchReq build() {
524543
return new SearchReq(this);
525544
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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.service.vector.request.aggregation;
21+
22+
import io.milvus.v2.exception.ErrorCode;
23+
import io.milvus.v2.exception.MilvusClientException;
24+
25+
public enum AggDirection {
26+
ASC("asc"),
27+
DESC("desc");
28+
29+
private final String value;
30+
31+
AggDirection(String value) {
32+
this.value = value;
33+
}
34+
35+
public String getValue() {
36+
return value;
37+
}
38+
39+
public static AggDirection fromValue(String value, String fieldName) {
40+
for (AggDirection direction : values()) {
41+
if (direction.value.equals(value)) {
42+
return direction;
43+
}
44+
}
45+
throw new MilvusClientException(ErrorCode.INVALID_PARAMS,
46+
fieldName + " must be 'asc' or 'desc'.");
47+
}
48+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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.service.vector.request.aggregation;
21+
22+
import io.milvus.v2.exception.ErrorCode;
23+
import io.milvus.v2.exception.MilvusClientException;
24+
25+
public enum MetricOps {
26+
AVG("avg"),
27+
SUM("sum"),
28+
COUNT("count"),
29+
MIN("min"),
30+
MAX("max");
31+
32+
private final String value;
33+
34+
MetricOps(String value) {
35+
this.value = value;
36+
}
37+
38+
public String getValue() {
39+
return value;
40+
}
41+
42+
public static MetricOps fromValue(String value) {
43+
for (MetricOps op : values()) {
44+
if (op.value.equals(value)) {
45+
return op;
46+
}
47+
}
48+
throw new MilvusClientException(ErrorCode.INVALID_PARAMS,
49+
"SearchAggregation metric op must be one of [avg, sum, count, min, max].");
50+
}
51+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
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.service.vector.request.aggregation;
21+
22+
import io.milvus.grpc.MetricAggSpec;
23+
import io.milvus.v2.exception.ErrorCode;
24+
import io.milvus.v2.exception.MilvusClientException;
25+
26+
public class MetricSpec {
27+
private final MetricOps op;
28+
private final String fieldName;
29+
30+
private MetricSpec(MetricSpecBuilder builder) {
31+
if (builder.op == null) {
32+
throw new MilvusClientException(ErrorCode.INVALID_PARAMS,
33+
"SearchAggregation metric op must not be null.");
34+
}
35+
if (builder.fieldName == null || builder.fieldName.isEmpty()) {
36+
throw new MilvusClientException(ErrorCode.INVALID_PARAMS,
37+
"SearchAggregation metric fieldName must not be empty.");
38+
}
39+
if (builder.op != MetricOps.COUNT && "*".equals(builder.fieldName)) {
40+
throw new MilvusClientException(ErrorCode.INVALID_PARAMS,
41+
"'*' is only valid for SearchAggregation count metrics.");
42+
}
43+
this.op = builder.op;
44+
this.fieldName = builder.fieldName;
45+
}
46+
47+
public static MetricSpecBuilder builder() {
48+
return new MetricSpecBuilder();
49+
}
50+
51+
public MetricOps getOp() {
52+
return op;
53+
}
54+
55+
public String getFieldName() {
56+
return fieldName;
57+
}
58+
59+
MetricAggSpec toProto() {
60+
return MetricAggSpec.newBuilder()
61+
.setOp(op.getValue())
62+
.setFieldName(fieldName)
63+
.build();
64+
}
65+
66+
@Override
67+
public String toString() {
68+
return "MetricSpec{" +
69+
"op=" + op +
70+
", fieldName='" + fieldName + '\'' +
71+
'}';
72+
}
73+
74+
public static class MetricSpecBuilder {
75+
private MetricOps op;
76+
private String fieldName;
77+
78+
private MetricSpecBuilder() {
79+
}
80+
81+
public MetricSpecBuilder op(MetricOps op) {
82+
this.op = op;
83+
return this;
84+
}
85+
86+
public MetricSpecBuilder fieldName(String fieldName) {
87+
this.fieldName = fieldName;
88+
return this;
89+
}
90+
91+
public MetricSpec build() {
92+
return new MetricSpec(this);
93+
}
94+
}
95+
96+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
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.service.vector.request.aggregation;
21+
22+
import io.milvus.v2.exception.ErrorCode;
23+
import io.milvus.v2.exception.MilvusClientException;
24+
25+
public class OrderSpec {
26+
private final String key;
27+
private final AggDirection direction;
28+
private final Boolean nullFirst;
29+
30+
private OrderSpec(OrderSpecBuilder builder) {
31+
if (builder.key == null || builder.key.isEmpty()) {
32+
throw new MilvusClientException(ErrorCode.INVALID_PARAMS,
33+
"SearchAggregation.order key must not be empty.");
34+
}
35+
if (builder.direction == null) {
36+
throw new MilvusClientException(ErrorCode.INVALID_PARAMS,
37+
"SearchAggregation.order direction must not be null.");
38+
}
39+
this.key = builder.key;
40+
this.direction = builder.direction;
41+
this.nullFirst = builder.nullFirst;
42+
}
43+
44+
public static OrderSpecBuilder builder() {
45+
return new OrderSpecBuilder();
46+
}
47+
48+
public String getKey() {
49+
return key;
50+
}
51+
52+
public AggDirection getDirection() {
53+
return direction;
54+
}
55+
56+
public Boolean getNullFirst() {
57+
return nullFirst;
58+
}
59+
60+
io.milvus.grpc.OrderSpec toProto() {
61+
io.milvus.grpc.OrderSpec.Builder builder = io.milvus.grpc.OrderSpec.newBuilder()
62+
.setKey(key)
63+
.setDirection(direction.getValue());
64+
if (nullFirst != null) {
65+
builder.setNullFirst(nullFirst);
66+
}
67+
return builder.build();
68+
}
69+
70+
@Override
71+
public String toString() {
72+
return "OrderSpec{" +
73+
"key='" + key + '\'' +
74+
", direction=" + direction +
75+
", nullFirst=" + nullFirst +
76+
'}';
77+
}
78+
79+
public static class OrderSpecBuilder {
80+
private String key;
81+
private AggDirection direction;
82+
private Boolean nullFirst;
83+
84+
private OrderSpecBuilder() {
85+
}
86+
87+
public OrderSpecBuilder key(String key) {
88+
this.key = key;
89+
return this;
90+
}
91+
92+
public OrderSpecBuilder direction(AggDirection direction) {
93+
this.direction = direction;
94+
return this;
95+
}
96+
97+
public OrderSpecBuilder nullFirst(Boolean nullFirst) {
98+
this.nullFirst = nullFirst;
99+
return this;
100+
}
101+
102+
public OrderSpec build() {
103+
return new OrderSpec(this);
104+
}
105+
}
106+
107+
}

0 commit comments

Comments
 (0)