Skip to content

Commit f84e94e

Browse files
committed
feat: add missing metadata fields
Although mentioned in the docs, featureProjection and classification are only available in GraphQL requests. AFAIK they're almost never used and are totally non-essential.
1 parent 48cb18f commit f84e94e

10 files changed

Lines changed: 198 additions & 55 deletions

File tree

src/it/java/io/weaviate/integration/DataITest.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ public void testCreateGetDelete() throws IOException {
4646

4747
var object = artists.query.byId(id, query -> query
4848
.returnProperties("name")
49-
.returnMetadata(Metadata.ID, Metadata.VECTOR));
49+
.returnMetadata(
50+
Metadata.UUID, Metadata.VECTOR,
51+
Metadata.CREATION_TIME_UNIX, Metadata.LAST_UPDATE_TIME_UNIX));
5052

5153
Assertions.assertThat(artists.data.exists(id))
5254
.as("object exists after insert").isTrue();
@@ -62,6 +64,11 @@ public void testCreateGetDelete() throws IOException {
6264
Assertions.assertThat(obj.properties())
6365
.as("has expected properties")
6466
.containsEntry("name", "john doe");
67+
68+
Assertions.assertThat(obj.metadata().creationTimeUnix())
69+
.as("creationTimeUnix").isNotNull();
70+
Assertions.assertThat(obj.metadata().lastUpdateTimeUnix())
71+
.as("lastUpdateTimeUnix").isNotNull();
6572
});
6673

6774
artists.data.delete(id);
@@ -249,7 +256,7 @@ public void testUpdate() throws IOException {
249256
.returnMetadata(Metadata.VECTOR)
250257
.returnReferences(
251258
QueryReference.single("writtenBy",
252-
writtenBy -> writtenBy.returnMetadata(Metadata.ID))));
259+
writtenBy -> writtenBy.returnMetadata(Metadata.UUID))));
253260

254261
Assertions.assertThat(updIvanhoe).get()
255262
.satisfies(book -> {
@@ -377,7 +384,7 @@ public void testReferenceAddMany() throws IOException {
377384
var goodburgAirports = cities.query.byId(goodburg.metadata().uuid(),
378385
city -> city.returnReferences(
379386
QueryReference.single("hasAirports",
380-
airport -> airport.returnMetadata(Metadata.ID))));
387+
airport -> airport.returnMetadata(Metadata.UUID))));
381388

382389
Assertions.assertThat(goodburgAirports).get()
383390
.as("Goodburg has 3 airports")

src/it/java/io/weaviate/integration/ReferencesITest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,9 @@ public void testReferences() throws IOException {
9595
var gotAlex = artists.query.byId(alex.metadata().uuid(),
9696
opt -> opt.returnReferences(
9797
QueryReference.multi("hasAwards", nsOscar,
98-
ref -> ref.returnMetadata(Metadata.ID)),
98+
ref -> ref.returnMetadata(Metadata.UUID)),
9999
QueryReference.multi("hasAwards", nsGrammy,
100-
ref -> ref.returnMetadata(Metadata.ID))));
100+
ref -> ref.returnMetadata(Metadata.UUID))));
101101

102102
Assertions.assertThat(gotAlex).get()
103103
.as("Artists: fetch by id including hasAwards references")
@@ -166,7 +166,7 @@ public void testNestedReferences() throws IOException {
166166
.returnReferences(
167167
QueryReference.single("presentedBy", r -> r.returnProperties("ceo")))
168168
// Grammy ID
169-
.returnMetadata(Metadata.ID))));
169+
.returnMetadata(Metadata.UUID))));
170170

171171
Assertions.assertThat(gotAlex).get()
172172
.as("Artists: fetch by id including nested references")

src/it/java/io/weaviate/integration/SearchITest.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,10 +358,20 @@ public void testHybrid() throws IOException {
358358
hobbies.data.insert(Map.of("name", "jetskiing", "description", "water sport"));
359359

360360
// Act
361-
var winterSport = hobbies.query.hybrid("winter");
361+
var winterSport = hobbies.query.hybrid("winter",
362+
hybrid -> hybrid
363+
.returnMetadata(Metadata.UUID, Metadata.SCORE, Metadata.EXPLAIN_SCORE));
364+
365+
// Assert
362366
Assertions.assertThat(winterSport.objects())
363367
.hasSize(1)
364368
.extracting(WeaviateObject::metadata).extracting(WeaviateMetadata::uuid)
365369
.containsOnly(skiing.metadata().uuid());
370+
371+
var first = winterSport.objects().get(0);
372+
Assertions.assertThat(first.metadata().score())
373+
.as("metadata::score").isNotNull();
374+
Assertions.assertThat(first.metadata().explainScore())
375+
.as("metadata::explainScore").isNotNull();
366376
}
367377
}

src/main/java/io/weaviate/client6/v1/api/collections/query/BaseQueryOptions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ final void appendTo(WeaviateProtoSearchGet.SearchRequest.Builder req) {
152152

153153
var metadata = WeaviateProtoSearchGet.MetadataRequest.newBuilder();
154154
if (returnMetadata.isEmpty()) {
155-
Metadata.ID.appendTo(metadata);
155+
Metadata.UUID.appendTo(metadata);
156156
} else {
157157
returnMetadata.forEach(m -> m.appendTo(metadata));
158158
}

src/main/java/io/weaviate/client6/v1/api/collections/query/ById.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,9 @@ public void appendTo(WeaviateProtoSearchGet.SearchRequest.Builder req) {
7474

7575
var metadata = WeaviateProtoSearchGet.MetadataRequest.newBuilder();
7676
if (returnMetadata.isEmpty()) {
77-
Metadata.ID.appendTo(metadata);
78-
} else {
79-
returnMetadata.forEach(m -> m.appendTo(metadata));
77+
returnMetadata.add(Metadata.UUID);
8078
}
79+
returnMetadata.forEach(m -> m.appendTo(metadata));
8180
req.setMetadata(metadata);
8281

8382
if (!returnProperties.isEmpty() || !returnReferences.isEmpty()) {

src/main/java/io/weaviate/client6/v1/api/collections/query/Metadata.java

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.weaviate.client6.v1.api.collections.query;
22

3+
import io.weaviate.client6.v1.api.collections.vectorindex.Distance;
34
import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoSearchGet;
45

56
/**
@@ -10,8 +11,101 @@
1011
public interface Metadata {
1112
void appendTo(WeaviateProtoSearchGet.MetadataRequest.Builder metadata);
1213

13-
public static final Metadata ID = MetadataField.ID;
14+
/** Include UUID of the object in the metadata response. */
15+
public static final Metadata UUID = MetadataField.UUID;
16+
/** Include associated vector in the metadata response. */
1417
public static final Metadata VECTOR = MetadataField.VECTOR;
18+
/** Include object creation time in the metadata response. */
19+
public static final Metadata CREATION_TIME_UNIX = MetadataField.CREATION_TIME_UNIX;
20+
/** Include last update time in the metadata response. */
21+
public static final Metadata LAST_UPDATE_TIME_UNIX = MetadataField.LAST_UPDATE_TIME_UNIX;
22+
/**
23+
* Include raw distance determined as part of the vector search.
24+
* The units will correspond to the distance metric configured for the vector
25+
* index; by default {@link Distance#COSINE}.
26+
*
27+
* <p>
28+
* Distance is only applicable to <strong>vector search results</strong>,
29+
* i.e. all {@code Near-} queries. Hybrid search will not return a distance,
30+
* as the BM25-VectorSearch fusion algorithm transforms the distance metric.
31+
*
32+
* @see <a href=
33+
* "https://forum.weaviate.io/t/issue-with-distance-value-in-weaviate-hybrid-search-and-applying-similarity-score-threshold/20443/3">
34+
* Distance metric in Hybrid search</a>
35+
*/
1536
public static final Metadata DISTANCE = MetadataField.DISTANCE;
37+
/**
38+
* Include certainty in the metadata response.
39+
*
40+
* <p>
41+
* Certainty is an <i>opinionated</i> measure that always returns a number
42+
* between 0 and 1. It is therefore usable with fixed-range distance metrics,
43+
* such as {@code cosine}.
44+
*
45+
* @see <a href=
46+
* "https://docs.weaviate.io/weaviate/config-refs/distances#distance-vs-certainty">
47+
* Distance vs. Certainty</a>
48+
*/
1649
public static final Metadata CERTAINTY = MetadataField.CERTAINTY;
50+
/**
51+
* Include {@code BM25F} score of the search result in the metadata response.
52+
*
53+
* <p>
54+
* {@link Metadata#SCORE} and {@link Metadata#EXPLAIN_SCORE} are only relevant
55+
* for Hybrid and BM25 search.
56+
*/
57+
public static final Metadata SCORE = MetadataField.SCORE;
58+
/**
59+
* Include the result score broken down into components.
60+
* The output is an unstructured string that is mostly useful for debugging
61+
* search results.
62+
*
63+
* <p>
64+
* {@link Metadata#SCORE} and {@link Metadata#EXPLAIN_SCORE} are only relevant
65+
* for Hybrid and BM25 search.
66+
*/
67+
public static final Metadata EXPLAIN_SCORE = MetadataField.EXPLAIN_SCORE;
68+
69+
/**
70+
* MetadataField are collection properties that can be requested for any object.
71+
*/
72+
enum MetadataField implements Metadata {
73+
UUID,
74+
VECTOR,
75+
CREATION_TIME_UNIX,
76+
LAST_UPDATE_TIME_UNIX,
77+
DISTANCE,
78+
CERTAINTY,
79+
SCORE,
80+
EXPLAIN_SCORE;
81+
82+
public void appendTo(WeaviateProtoSearchGet.MetadataRequest.Builder metadata) {
83+
switch (this) {
84+
case UUID:
85+
metadata.setUuid(true);
86+
break;
87+
case VECTOR:
88+
metadata.setVector(true);
89+
break;
90+
case CREATION_TIME_UNIX:
91+
metadata.setCreationTimeUnix(true);
92+
break;
93+
case LAST_UPDATE_TIME_UNIX:
94+
metadata.setLastUpdateTimeUnix(true);
95+
break;
96+
case DISTANCE:
97+
metadata.setDistance(true);
98+
break;
99+
case CERTAINTY:
100+
metadata.setCertainty(true);
101+
break;
102+
case EXPLAIN_SCORE:
103+
metadata.setExplainScore(true);
104+
break;
105+
case SCORE:
106+
metadata.setScore(true);
107+
break;
108+
}
109+
}
110+
}
17111
}

src/main/java/io/weaviate/client6/v1/api/collections/query/MetadataField.java

Lines changed: 0 additions & 30 deletions
This file was deleted.

src/main/java/io/weaviate/client6/v1/api/collections/query/QueryMetadata.java

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,57 @@
44
import io.weaviate.client6.v1.api.collections.WeaviateMetadata;
55
import io.weaviate.client6.v1.internal.ObjectBuilder;
66

7-
public record QueryMetadata(String uuid, Float distance, Float certainty, Vectors vectors) implements WeaviateMetadata {
7+
public record QueryMetadata(String uuid,
8+
Vectors vectors,
9+
Long creationTimeUnix,
10+
Long lastUpdateTimeUnix,
11+
Float distance,
12+
Float certainty,
13+
Float score,
14+
String explainScore) implements WeaviateMetadata {
815

916
private QueryMetadata(Builder builder) {
10-
this(builder.uuid, builder.distance, builder.certainty, builder.vectors);
17+
this(
18+
builder.uuid,
19+
builder.vectors,
20+
builder.creationTimeUnix,
21+
builder.lastUpdateTimeUnix,
22+
builder.distance,
23+
builder.certainty,
24+
builder.score,
25+
builder.explainScore);
1126
}
1227

1328
public static class Builder implements ObjectBuilder<QueryMetadata> {
1429
private String uuid;
30+
private Vectors vectors;
31+
private Long creationTimeUnix;
32+
private Long lastUpdateTimeUnix;
1533
private Float distance;
1634
private Float certainty;
17-
private Vectors vectors;
35+
private Float score;
36+
private String explainScore;
1837

1938
public final Builder uuid(String uuid) {
2039
this.uuid = uuid;
2140
return this;
2241
}
2342

43+
public final Builder vectors(Vectors vectors) {
44+
this.vectors = vectors;
45+
return this;
46+
}
47+
48+
public final Builder creationTimeUnix(Long creationTimeUnix) {
49+
this.creationTimeUnix = creationTimeUnix;
50+
return this;
51+
}
52+
53+
public final Builder lastUpdateTimeUnix(Long lastUpdateTimeUnix) {
54+
this.lastUpdateTimeUnix = lastUpdateTimeUnix;
55+
return this;
56+
}
57+
2458
public final Builder distance(Float distance) {
2559
this.distance = distance;
2660
return this;
@@ -31,8 +65,13 @@ public final Builder certainty(Float certainty) {
3165
return this;
3266
}
3367

34-
public final Builder vectors(Vectors vectors) {
35-
this.vectors = vectors;
68+
public final Builder score(Float score) {
69+
this.score = score;
70+
return this;
71+
}
72+
73+
public final Builder explainScore(String explainScore) {
74+
this.explainScore = explainScore;
3675
return this;
3776
}
3877

src/main/java/io/weaviate/client6/v1/api/collections/query/QueryRequest.java

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,33 @@ private static <T> WeaviateObject<T, Object, QueryMetadata> unmarshalResultObjec
8686
WeaviateProtoSearchGet.PropertiesResult propertiesResult,
8787
WeaviateProtoSearchGet.MetadataResult metadataResult,
8888
CollectionDescriptor<T> descriptor) {
89-
var res = unmarshalReferences(propertiesResult, metadataResult, descriptor);
89+
var object = unmarshalWithReferences(propertiesResult, metadataResult, descriptor);
9090
var metadata = new QueryMetadata.Builder()
91-
.uuid(res.metadata().uuid())
92-
.distance(metadataResult.getDistance())
93-
.certainty(metadataResult.getCertainty())
94-
.vectors(res.metadata().vectors());
95-
return new WeaviateObject<>(descriptor.name(), res.properties(), res.references(), metadata.build());
91+
.uuid(object.metadata().uuid())
92+
.vectors(object.metadata().vectors());
93+
94+
if (metadataResult.getCreationTimeUnixPresent()) {
95+
metadata.creationTimeUnix(metadataResult.getCreationTimeUnix());
96+
}
97+
if (metadataResult.getLastUpdateTimeUnixPresent()) {
98+
metadata.lastUpdateTimeUnix(metadataResult.getLastUpdateTimeUnix());
99+
}
100+
if (metadataResult.getDistancePresent()) {
101+
metadata.distance(metadataResult.getDistance());
102+
}
103+
if (metadataResult.getCertaintyPresent()) {
104+
metadata.certainty(metadataResult.getCertainty());
105+
}
106+
if (metadataResult.getScorePresent()) {
107+
metadata.score(metadataResult.getScore());
108+
}
109+
if (metadataResult.getExplainScorePresent()) {
110+
metadata.explainScore(metadataResult.getExplainScore());
111+
}
112+
return new WeaviateObject<>(descriptor.name(), object.properties(), object.references(), metadata.build());
96113
}
97114

98-
private static <T> WeaviateObject<T, Object, ObjectMetadata> unmarshalReferences(
115+
private static <T> WeaviateObject<T, Object, ObjectMetadata> unmarshalWithReferences(
99116
WeaviateProtoSearchGet.PropertiesResult propertiesResult,
100117
WeaviateProtoSearchGet.MetadataResult metadataResult,
101118
CollectionDescriptor<T> descriptor) {
@@ -114,7 +131,7 @@ private static <T> WeaviateObject<T, Object, ObjectMetadata> unmarshalReferences
114131
(map, ref) -> {
115132
var refObjects = ref.getPropertiesList().stream()
116133
.map(property -> {
117-
var reference = unmarshalReferences(
134+
var reference = unmarshalWithReferences(
118135
property, property.getMetadata(),
119136
// TODO: this should be possible to configure for ODM?
120137
CollectionDescriptor.ofMap(property.getTargetCollection()));

src/main/java/io/weaviate/client6/v1/api/collections/vectorindex/Distance.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
import com.google.gson.annotations.SerializedName;
44

5+
/**
6+
* Distance metrics supported for vector search.
7+
*
8+
* @see <a href=
9+
* "https://docs.weaviate.io/weaviate/config-refs/distances#available-distance-metrics">Availabe
10+
* distance metrics in Weaviate</a>
11+
*/
512
public enum Distance {
613
@SerializedName("cosine")
714
COSINE,

0 commit comments

Comments
 (0)