diff --git a/src/it/java/io/weaviate/integration/DataITest.java b/src/it/java/io/weaviate/integration/DataITest.java index 827236163..f5c1957fe 100644 --- a/src/it/java/io/weaviate/integration/DataITest.java +++ b/src/it/java/io/weaviate/integration/DataITest.java @@ -46,7 +46,9 @@ public void testCreateGetDelete() throws IOException { var object = artists.query.byId(id, query -> query .returnProperties("name") - .returnMetadata(Metadata.ID, Metadata.VECTOR)); + .returnMetadata( + Metadata.UUID, Metadata.VECTOR, + Metadata.CREATION_TIME_UNIX, Metadata.LAST_UPDATE_TIME_UNIX)); Assertions.assertThat(artists.data.exists(id)) .as("object exists after insert").isTrue(); @@ -62,6 +64,11 @@ public void testCreateGetDelete() throws IOException { Assertions.assertThat(obj.properties()) .as("has expected properties") .containsEntry("name", "john doe"); + + Assertions.assertThat(obj.metadata().creationTimeUnix()) + .as("creationTimeUnix").isNotNull(); + Assertions.assertThat(obj.metadata().lastUpdateTimeUnix()) + .as("lastUpdateTimeUnix").isNotNull(); }); artists.data.delete(id); @@ -249,7 +256,7 @@ public void testUpdate() throws IOException { .returnMetadata(Metadata.VECTOR) .returnReferences( QueryReference.single("writtenBy", - writtenBy -> writtenBy.returnMetadata(Metadata.ID)))); + writtenBy -> writtenBy.returnMetadata(Metadata.UUID)))); Assertions.assertThat(updIvanhoe).get() .satisfies(book -> { @@ -377,7 +384,7 @@ public void testReferenceAddMany() throws IOException { var goodburgAirports = cities.query.byId(goodburg.metadata().uuid(), city -> city.returnReferences( QueryReference.single("hasAirports", - airport -> airport.returnMetadata(Metadata.ID)))); + airport -> airport.returnMetadata(Metadata.UUID)))); Assertions.assertThat(goodburgAirports).get() .as("Goodburg has 3 airports") diff --git a/src/it/java/io/weaviate/integration/ReferencesITest.java b/src/it/java/io/weaviate/integration/ReferencesITest.java index 8ee613b4f..b28bb907f 100644 --- a/src/it/java/io/weaviate/integration/ReferencesITest.java +++ b/src/it/java/io/weaviate/integration/ReferencesITest.java @@ -95,9 +95,9 @@ public void testReferences() throws IOException { var gotAlex = artists.query.byId(alex.metadata().uuid(), opt -> opt.returnReferences( QueryReference.multi("hasAwards", nsOscar, - ref -> ref.returnMetadata(Metadata.ID)), + ref -> ref.returnMetadata(Metadata.UUID)), QueryReference.multi("hasAwards", nsGrammy, - ref -> ref.returnMetadata(Metadata.ID)))); + ref -> ref.returnMetadata(Metadata.UUID)))); Assertions.assertThat(gotAlex).get() .as("Artists: fetch by id including hasAwards references") @@ -166,7 +166,7 @@ public void testNestedReferences() throws IOException { .returnReferences( QueryReference.single("presentedBy", r -> r.returnProperties("ceo"))) // Grammy ID - .returnMetadata(Metadata.ID)))); + .returnMetadata(Metadata.UUID)))); Assertions.assertThat(gotAlex).get() .as("Artists: fetch by id including nested references") diff --git a/src/it/java/io/weaviate/integration/SearchITest.java b/src/it/java/io/weaviate/integration/SearchITest.java index 3f67240a5..c6283e651 100644 --- a/src/it/java/io/weaviate/integration/SearchITest.java +++ b/src/it/java/io/weaviate/integration/SearchITest.java @@ -358,10 +358,20 @@ public void testHybrid() throws IOException { hobbies.data.insert(Map.of("name", "jetskiing", "description", "water sport")); // Act - var winterSport = hobbies.query.hybrid("winter"); + var winterSport = hobbies.query.hybrid("winter", + hybrid -> hybrid + .returnMetadata(Metadata.UUID, Metadata.SCORE, Metadata.EXPLAIN_SCORE)); + + // Assert Assertions.assertThat(winterSport.objects()) .hasSize(1) .extracting(WeaviateObject::metadata).extracting(WeaviateMetadata::uuid) .containsOnly(skiing.metadata().uuid()); + + var first = winterSport.objects().get(0); + Assertions.assertThat(first.metadata().score()) + .as("metadata::score").isNotNull(); + Assertions.assertThat(first.metadata().explainScore()) + .as("metadata::explainScore").isNotNull(); } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/BaseQueryOptions.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/BaseQueryOptions.java index 3a2815864..ffda94ab9 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/BaseQueryOptions.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/BaseQueryOptions.java @@ -152,7 +152,7 @@ final void appendTo(WeaviateProtoSearchGet.SearchRequest.Builder req) { var metadata = WeaviateProtoSearchGet.MetadataRequest.newBuilder(); if (returnMetadata.isEmpty()) { - Metadata.ID.appendTo(metadata); + Metadata.UUID.appendTo(metadata); } else { returnMetadata.forEach(m -> m.appendTo(metadata)); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/ById.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/ById.java index f2e37f6a4..3c256b3b5 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/ById.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/ById.java @@ -74,10 +74,9 @@ public void appendTo(WeaviateProtoSearchGet.SearchRequest.Builder req) { var metadata = WeaviateProtoSearchGet.MetadataRequest.newBuilder(); if (returnMetadata.isEmpty()) { - Metadata.ID.appendTo(metadata); - } else { - returnMetadata.forEach(m -> m.appendTo(metadata)); + returnMetadata.add(Metadata.UUID); } + returnMetadata.forEach(m -> m.appendTo(metadata)); req.setMetadata(metadata); if (!returnProperties.isEmpty() || !returnReferences.isEmpty()) { diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/Metadata.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/Metadata.java index 62396632f..3a0574b56 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/Metadata.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/Metadata.java @@ -1,5 +1,6 @@ package io.weaviate.client6.v1.api.collections.query; +import io.weaviate.client6.v1.api.collections.vectorindex.Distance; import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoSearchGet; /** @@ -10,8 +11,101 @@ public interface Metadata { void appendTo(WeaviateProtoSearchGet.MetadataRequest.Builder metadata); - public static final Metadata ID = MetadataField.ID; + /** Include UUID of the object in the metadata response. */ + public static final Metadata UUID = MetadataField.UUID; + /** Include associated vector in the metadata response. */ public static final Metadata VECTOR = MetadataField.VECTOR; + /** Include object creation time in the metadata response. */ + public static final Metadata CREATION_TIME_UNIX = MetadataField.CREATION_TIME_UNIX; + /** Include last update time in the metadata response. */ + public static final Metadata LAST_UPDATE_TIME_UNIX = MetadataField.LAST_UPDATE_TIME_UNIX; + /** + * Include raw distance determined as part of the vector search. + * The units will correspond to the distance metric configured for the vector + * index; by default {@link Distance#COSINE}. + * + *
+ * Distance is only applicable to vector search results, + * i.e. all {@code Near-} queries. Hybrid search will not return a distance, + * as the BM25-VectorSearch fusion algorithm transforms the distance metric. + * + * @see + * Distance metric in Hybrid search + */ public static final Metadata DISTANCE = MetadataField.DISTANCE; + /** + * Include certainty in the metadata response. + * + *
+ * Certainty is an opinionated measure that always returns a number + * between 0 and 1. It is therefore usable with fixed-range distance metrics, + * such as {@code cosine}. + * + * @see + * Distance vs. Certainty + */ public static final Metadata CERTAINTY = MetadataField.CERTAINTY; + /** + * Include {@code BM25F} score of the search result in the metadata response. + * + *
+ * {@link Metadata#SCORE} and {@link Metadata#EXPLAIN_SCORE} are only relevant + * for Hybrid and BM25 search. + */ + public static final Metadata SCORE = MetadataField.SCORE; + /** + * Include the result score broken down into components. + * The output is an unstructured string that is mostly useful for debugging + * search results. + * + *
+ * {@link Metadata#SCORE} and {@link Metadata#EXPLAIN_SCORE} are only relevant
+ * for Hybrid and BM25 search.
+ */
+ public static final Metadata EXPLAIN_SCORE = MetadataField.EXPLAIN_SCORE;
+
+ /**
+ * MetadataField are collection properties that can be requested for any object.
+ */
+ enum MetadataField implements Metadata {
+ UUID,
+ VECTOR,
+ CREATION_TIME_UNIX,
+ LAST_UPDATE_TIME_UNIX,
+ DISTANCE,
+ CERTAINTY,
+ SCORE,
+ EXPLAIN_SCORE;
+
+ public void appendTo(WeaviateProtoSearchGet.MetadataRequest.Builder metadata) {
+ switch (this) {
+ case UUID:
+ metadata.setUuid(true);
+ break;
+ case VECTOR:
+ metadata.setVector(true);
+ break;
+ case CREATION_TIME_UNIX:
+ metadata.setCreationTimeUnix(true);
+ break;
+ case LAST_UPDATE_TIME_UNIX:
+ metadata.setLastUpdateTimeUnix(true);
+ break;
+ case DISTANCE:
+ metadata.setDistance(true);
+ break;
+ case CERTAINTY:
+ metadata.setCertainty(true);
+ break;
+ case EXPLAIN_SCORE:
+ metadata.setExplainScore(true);
+ break;
+ case SCORE:
+ metadata.setScore(true);
+ break;
+ }
+ }
+ }
}
diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/MetadataField.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/MetadataField.java
deleted file mode 100644
index 3f2fcdf82..000000000
--- a/src/main/java/io/weaviate/client6/v1/api/collections/query/MetadataField.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package io.weaviate.client6.v1.api.collections.query;
-
-import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoSearchGet;
-
-/**
- * MetadataField are collection properties that can be requested for any object.
- */
-public enum MetadataField implements Metadata {
- ID,
- VECTOR,
- DISTANCE,
- CERTAINTY;
-
- public void appendTo(WeaviateProtoSearchGet.MetadataRequest.Builder metadata) {
- switch (this) {
- case ID:
- metadata.setUuid(true);
- break;
- case VECTOR:
- metadata.setVector(true);
- break;
- case DISTANCE:
- metadata.setDistance(true);
- break;
- case CERTAINTY:
- metadata.setCertainty(true);
- break;
- }
- }
-}
diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryMetadata.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryMetadata.java
index d54678e67..3573292ab 100644
--- a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryMetadata.java
+++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryMetadata.java
@@ -4,23 +4,57 @@
import io.weaviate.client6.v1.api.collections.WeaviateMetadata;
import io.weaviate.client6.v1.internal.ObjectBuilder;
-public record QueryMetadata(String uuid, Float distance, Float certainty, Vectors vectors) implements WeaviateMetadata {
+public record QueryMetadata(String uuid,
+ Vectors vectors,
+ Long creationTimeUnix,
+ Long lastUpdateTimeUnix,
+ Float distance,
+ Float certainty,
+ Float score,
+ String explainScore) implements WeaviateMetadata {
private QueryMetadata(Builder builder) {
- this(builder.uuid, builder.distance, builder.certainty, builder.vectors);
+ this(
+ builder.uuid,
+ builder.vectors,
+ builder.creationTimeUnix,
+ builder.lastUpdateTimeUnix,
+ builder.distance,
+ builder.certainty,
+ builder.score,
+ builder.explainScore);
}
public static class Builder implements ObjectBuilder