From 430397d169882eb35962386ec917203ab7fd0504 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Wed, 19 Nov 2025 15:02:36 +0100 Subject: [PATCH 01/11] refactor: use dedicated WriteWeaviateObject in .data operations --- .../io/weaviate/integration/DataITest.java | 28 +-- .../v1/api/collections/ObjectMetadata.java | 2 +- .../client6/v1/api/collections/Vectors.java | 19 ++ .../api/collections/data/BatchReference.java | 12 +- .../collections/data/InsertManyRequest.java | 114 +++++------- .../collections/data/InsertObjectRequest.java | 76 +++----- .../v1/api/collections/data/Reference.java | 9 +- .../data/ReplaceObjectRequest.java | 58 +++--- .../collections/data/UpdateObjectRequest.java | 57 +++--- .../collections/data/WeaviateDataClient.java | 37 ++-- .../data/WeaviateDataClientAsync.java | 28 +-- .../collections/data/WriteWeaviateObject.java | 174 ++++++++++++------ 12 files changed, 337 insertions(+), 277 deletions(-) diff --git a/src/it/java/io/weaviate/integration/DataITest.java b/src/it/java/io/weaviate/integration/DataITest.java index 27c3aafec..24aa43205 100644 --- a/src/it/java/io/weaviate/integration/DataITest.java +++ b/src/it/java/io/weaviate/integration/DataITest.java @@ -99,7 +99,7 @@ public void testBlobData() throws IOException { "breed", "ragdoll", "img", ragdollPng)); - var got = cats.query.byId(ragdoll.metadata().uuid(), + var got = cats.query.byId(ragdoll.uuid(), cat -> cat.returnProperties("img")); Assertions.assertThat(got).get() @@ -140,12 +140,12 @@ public void testReferences_AddReplaceDelete() throws IOException { // Act: add reference persons.data.referenceAdd( - john.metadata().uuid(), + john.uuid(), "hasFriend", Reference.object(albie)); // Assert - var johnWithFriends = persons.query.byId(john.metadata().uuid(), + var johnWithFriends = persons.query.byId(john.uuid(), query -> query.returnReferences( QueryReference.single("hasFriend", friend -> friend.returnProperties("name")))); @@ -161,11 +161,11 @@ public void testReferences_AddReplaceDelete() throws IOException { // Act: replace reference var barbara = persons.data.insert(Map.of("name", "barbara")); persons.data.referenceReplace( - john.metadata().uuid(), + john.uuid(), "hasFriend", Reference.object(barbara)); - johnWithFriends = persons.query.byId(john.metadata().uuid(), + johnWithFriends = persons.query.byId(john.uuid(), query -> query.returnReferences( QueryReference.single("hasFriend", friend -> friend.returnProperties("name")))); @@ -180,12 +180,12 @@ public void testReferences_AddReplaceDelete() throws IOException { // Act: delete reference persons.data.referenceDelete( - john.metadata().uuid(), + john.uuid(), "hasFriend", Reference.object(barbara)); // Assert - johnWithFriends = persons.query.byId(john.metadata().uuid(), + johnWithFriends = persons.query.byId(john.uuid(), query -> query.returnReferences( QueryReference.single("hasFriend"))); @@ -210,11 +210,11 @@ public void testReplace() throws IOException { var ivanhoe = books.data.insert(Map.of("title", "ivanhoe")); // Act - books.data.replace(ivanhoe.metadata().uuid(), + books.data.replace(ivanhoe.uuid(), replace -> replace.properties(Map.of("year", 1819))); // Assert - var replacedIvanhoe = books.query.byId(ivanhoe.metadata().uuid()); + var replacedIvanhoe = books.query.byId(ivanhoe.uuid()); Assertions.assertThat(replacedIvanhoe).get() .as("has ONLY year property") @@ -251,7 +251,7 @@ public void testUpdate() throws IOException { var ivanhoe = books.data.insert(Map.of("title", "ivanhoe")); // Act - books.data.update(ivanhoe.metadata().uuid(), + books.data.update(ivanhoe.uuid(), update -> update .properties(Map.of("year", 1819)) .reference("writtenBy", Reference.objects(walter)) @@ -259,7 +259,7 @@ public void testUpdate() throws IOException { // Assert var updIvanhoe = books.query.byId( - ivanhoe.metadata().uuid(), + ivanhoe.uuid(), query -> query .includeVector() .returnReferences(QueryReference.single("writtenBy"))); @@ -298,8 +298,8 @@ public void testDeleteMany() throws IOException { var things = client.collections.use(nsThings); things.data.insert(Map.of("last_used", 1)); - var delete_1 = things.data.insert(Map.of("last_used", 5)).metadata().uuid(); - var delete_2 = things.data.insert(Map.of("last_used", 9)).metadata().uuid(); + var delete_1 = things.data.insert(Map.of("last_used", 5)).uuid(); + var delete_2 = things.data.insert(Map.of("last_used", 9)).uuid(); // Act (dry run) things.data.deleteMany( @@ -387,7 +387,7 @@ public void testReferenceAddMany() throws IOException { // Assert Assertions.assertThat(response.errors()).isEmpty(); - var goodburgAirports = cities.query.byId(goodburg.metadata().uuid(), + var goodburgAirports = cities.query.byId(goodburg.uuid(), city -> city.returnReferences( QueryReference.single("hasAirports"))); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/ObjectMetadata.java b/src/main/java/io/weaviate/client6/v1/api/collections/ObjectMetadata.java index 4dcaed6a5..e467644c7 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/ObjectMetadata.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/ObjectMetadata.java @@ -11,7 +11,7 @@ public record ObjectMetadata( @SerializedName("id") String uuid, @SerializedName("vectors") Vectors vectors, @SerializedName("creationTimeUnix") Long createdAt, - @SerializedName("lastUpdateTImeUnix") Long lastUpdatedAt) implements WeaviateMetadata { + @SerializedName("lastUpdateTimeUnix") Long lastUpdatedAt) implements WeaviateMetadata { public ObjectMetadata(Builder builder) { this(builder.uuid, builder.vectors, null, null); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/Vectors.java b/src/main/java/io/weaviate/client6/v1/api/collections/Vectors.java index a1e9e8796..1a0b3203b 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/Vectors.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/Vectors.java @@ -81,6 +81,20 @@ public Vectors(Vectors... vectors) { this.vectorsMap = namedVectors; } + /** + * Add more vector objects. + * + * @param vectors Vector objects. + * @return A new {@code Vectors} object containing all vectors. + */ + public Vectors withVectors(Vectors... vectors) { + var combined = new HashMap<>(vectorsMap); + for (var v : vectors) { + combined.putAll(v.vectorsMap); + } + return new Vectors(combined); + } + /** * Check if a vector exists in the query result. * @@ -90,6 +104,11 @@ public boolean contains(String name) { return vectorsMap.containsKey(name); } + /** Returns the number of vectors contained. */ + public int size() { + return vectorsMap.size(); + } + /** * Get 1-dimensional vector by name. * diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/BatchReference.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/BatchReference.java index 8e14a04ec..c75220a26 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/BatchReference.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/BatchReference.java @@ -7,24 +7,24 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; -import io.weaviate.client6.v1.api.collections.WeaviateObject; +import io.weaviate.client6.v1.api.collections.IWeaviateObject; public record BatchReference(String fromCollection, String fromProperty, String fromUuid, Reference reference) { - public static BatchReference[] objects(WeaviateObject fromObject, String fromProperty, - WeaviateObject... toObjects) { + public static BatchReference[] objects(IWeaviateObject fromObject, String fromProperty, + IWeaviateObject... toObjects) { return Arrays.stream(toObjects) .map(to -> new BatchReference( - fromObject.collection(), fromProperty, fromObject.metadata().uuid(), + fromObject.collection(), fromProperty, fromObject.uuid(), Reference.object(to))) .toArray(BatchReference[]::new); } - public static BatchReference[] uuids(WeaviateObject fromObject, String fromProperty, + public static BatchReference[] uuids(IWeaviateObject fromObject, String fromProperty, String... toUuids) { return Arrays.stream(toUuids) .map(to -> new BatchReference( - fromObject.collection(), fromProperty, fromObject.metadata().uuid(), + fromObject.collection(), fromProperty, fromObject.uuid(), Reference.uuids(to))) .toArray(BatchReference[]::new); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/InsertManyRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/InsertManyRequest.java index c41a51057..161e4489d 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/InsertManyRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/InsertManyRequest.java @@ -9,9 +9,7 @@ import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; import io.weaviate.client6.v1.api.collections.GeoCoordinates; -import io.weaviate.client6.v1.api.collections.ObjectMetadata; import io.weaviate.client6.v1.api.collections.PhoneNumber; -import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.internal.MapUtil; import io.weaviate.client6.v1.internal.grpc.ByteStringUtil; import io.weaviate.client6.v1.internal.grpc.Rpc; @@ -22,25 +20,25 @@ import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBatch; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; -public record InsertManyRequest(List> objects) { +public record InsertManyRequest(List> objects) { @SafeVarargs - public InsertManyRequest(WeaviateObject... objects) { + public InsertManyRequest(WriteWeaviateObject... objects) { this(Arrays.asList(objects)); } + @SuppressWarnings("unchecked") @SafeVarargs - public static final InsertManyRequest of(T... properties) { + public static final InsertManyRequest of(PropertiesT... properties) { var objects = Arrays.stream(properties) - .map(p -> WeaviateObject.of( - obj -> obj.properties(p).metadata(ObjectMetadata.of()))) + .map(p -> (WriteWeaviateObject) WriteWeaviateObject.of(obj -> obj.properties(p))) .toList(); - return new InsertManyRequest(objects); + return new InsertManyRequest<>(objects); } - public static Rpc, WeaviateProtoBatch.BatchObjectsRequest, InsertManyResponse, WeaviateProtoBatch.BatchObjectsReply> rpc( - List> insertObjects, - CollectionDescriptor collection, + public static Rpc, WeaviateProtoBatch.BatchObjectsRequest, InsertManyResponse, WeaviateProtoBatch.BatchObjectsReply> rpc( + List> insertObjects, + CollectionDescriptor collection, CollectionHandleDefaults defaults) { return Rpc.insert( request -> { @@ -75,8 +73,8 @@ public static Rpc, WeaviateProtoBatch.BatchObjectsReque while (iter.hasNext()) { var idx = iter.nextIndex(); var next = iter.next(); - var uuid = next.metadata() != null ? next.metadata().uuid() : null; + var uuid = next.uuid(); if (failed.containsKey(idx)) { var err = failed.get(idx); errors.add(err); @@ -94,72 +92,62 @@ public static Rpc, WeaviateProtoBatch.BatchObjectsReque } public static void buildObject(WeaviateProtoBatch.BatchObject.Builder object, - WeaviateObject insert, + WriteWeaviateObject insert, CollectionDescriptor collection, CollectionHandleDefaults defaults) { object.setCollection(collection.collectionName()); - var metadata = insert.metadata(); - if (metadata != null) { - object.setUuid(metadata.uuid()); - - if (metadata.vectors() != null) { - var vectors = metadata.vectors().asMap() - .entrySet().stream().map(entry -> { - var value = entry.getValue(); - var vector = WeaviateProtoBase.Vectors.newBuilder() - .setName(entry.getKey()); - - if (value instanceof float[] single) { - vector.setType(VectorType.VECTOR_TYPE_SINGLE_FP32); - vector.setVectorBytes(ByteStringUtil.encodeVectorSingle(single)); - } else if (value instanceof float[][] multi) { - vector.setVectorBytes(ByteStringUtil.encodeVectorMulti(multi)); - vector.setType(VectorType.VECTOR_TYPE_MULTI_FP32); - } - - return vector.build(); - }).toList(); - object.addAllVectors(vectors); - } - if (defaults.tenant() != null) { - object.setTenant(defaults.tenant()); - } + object.setUuid(insert.uuid()); + + if (insert.vectors() != null) { + var vectors = insert.vectors().asMap() + .entrySet().stream().map(entry -> { + var value = entry.getValue(); + var vector = WeaviateProtoBase.Vectors.newBuilder() + .setName(entry.getKey()); + + if (value instanceof float[] single) { + vector.setType(VectorType.VECTOR_TYPE_SINGLE_FP32); + vector.setVectorBytes(ByteStringUtil.encodeVectorSingle(single)); + } else if (value instanceof float[][] multi) { + vector.setVectorBytes(ByteStringUtil.encodeVectorMulti(multi)); + vector.setType(VectorType.VECTOR_TYPE_MULTI_FP32); + } + + return vector.build(); + }).toList(); + object.addAllVectors(vectors); + } + if (defaults.tenant() != null) { + object.setTenant(defaults.tenant()); } var singleRef = new ArrayList(); var multiRef = new ArrayList(); - insert.references() - .entrySet().stream().forEach(entry -> { - var references = entry.getValue(); - - // dyma: How are we supposed to know if the reference - // is single- or multi-target? - for (var ref : references) { - if (ref.collection() == null) { - singleRef.add( - WeaviateProtoBatch.BatchObject.SingleTargetRefProps.newBuilder() - .addAllUuids(ref.uuids()) - .setPropName(entry.getKey()) - .build()); - } else { - multiRef.add( - WeaviateProtoBatch.BatchObject.MultiTargetRefProps.newBuilder() - .setTargetCollection(ref.collection()) - .addAllUuids(ref.uuids()) - .setPropName(entry.getKey()) - .build()); - } - } - }); + insert.references().entrySet().stream().forEach(entry -> { + var references = entry.getValue(); + + // dyma: How are we supposed to know if the reference + // is single- or multi-target? + for (var ref : references) { + if (ref.collection() == null) { + singleRef.add(WeaviateProtoBatch.BatchObject.SingleTargetRefProps.newBuilder().addAllUuids(ref.uuids()) + .setPropName(entry.getKey()).build()); + } else { + multiRef.add(WeaviateProtoBatch.BatchObject.MultiTargetRefProps.newBuilder() + .setTargetCollection(ref.collection()).addAllUuids(ref.uuids()).setPropName(entry.getKey()).build()); + } + } + }); var properties = WeaviateProtoBatch.BatchObject.Properties.newBuilder() .addAllSingleTargetRefProps(singleRef) .addAllMultiTargetRefProps(multiRef); if (insert.properties() != null) { - var nonRef = marshalStruct(collection.propertiesReader(insert.properties()).readProperties()); + var nonRef = marshalStruct(collection.propertiesReader(insert.properties()) + .readProperties()); properties.setNonRefProperties(nonRef); } object.setProperties(properties); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/InsertObjectRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/InsertObjectRequest.java index fc57c2882..05ab58172 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/InsertObjectRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/InsertObjectRequest.java @@ -7,21 +7,22 @@ import com.google.gson.reflect.TypeToken; import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; -import io.weaviate.client6.v1.api.collections.ObjectMetadata; -import io.weaviate.client6.v1.api.collections.Vectors; -import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.internal.ObjectBuilder; import io.weaviate.client6.v1.internal.json.JSON; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; import io.weaviate.client6.v1.internal.rest.Endpoint; import io.weaviate.client6.v1.internal.rest.SimpleEndpoint; -public record InsertObjectRequest(WeaviateObject object) { +public record InsertObjectRequest(WriteWeaviateObject object) { @SuppressWarnings("unchecked") - public static final Endpoint, WeaviateObject> endpoint( - CollectionDescriptor collection, + public static final Endpoint, WriteWeaviateObject> endpoint( + CollectionDescriptor collection, CollectionHandleDefaults defaults) { + + final var typeToken = (TypeToken>) TypeToken + .getParameterized(WriteWeaviateObject.class, collection.typeToken().getType()); + return new SimpleEndpoint<>( request -> "POST", request -> "/objects/", @@ -29,55 +30,26 @@ public static final Endpoint, WeaviateObject JSON.serialize( - new WriteWeaviateObject<>(request.object, defaults.tenant()), - TypeToken.getParameterized( - WriteWeaviateObject.class, collection.typeToken().getType())), - (statusCode, response) -> JSON.deserialize(response, - (TypeToken>) TypeToken.getParameterized( - WeaviateObject.class, collection.typeToken().getType(), Object.class, ObjectMetadata.class))); - } - - public static InsertObjectRequest of(String collectionName, T properties) { - return of(collectionName, properties, ObjectBuilder.identity()); - } - - public static InsertObjectRequest of(String collectionName, T properties, - Function, ObjectBuilder>> fn) { - return fn.apply(new Builder(collectionName, properties)).build(); + new WriteWeaviateObject<>( + request.object.uuid(), + request.object.collection(), + defaults.tenant(), + request.object.properties(), + request.object.vectors(), + request.object.createdAt(), + request.object.lastUpdatedAt(), + request.object.references()), + typeToken), + (statusCode, response) -> JSON.deserialize(response, typeToken)); } - public InsertObjectRequest(Builder builder) { - this(builder.object.build()); + static InsertObjectRequest of(PropertiesT properties) { + return of(properties, ObjectBuilder.identity()); } - public static class Builder implements ObjectBuilder> { - private final WeaviateObject.Builder object = new WeaviateObject.Builder<>(); - private final ObjectMetadata.Builder metadata = new ObjectMetadata.Builder(); - - public Builder(String collectionName, T properties) { - this.object.collection(collectionName).properties(properties); - } - - public Builder uuid(String uuid) { - this.metadata.uuid(uuid); - return this; - } - - public Builder vectors(Vectors... vectors) { - this.metadata.vectors(vectors); - return this; - } - - public Builder reference(String property, Reference... references) { - this.object.reference(property, references); - return this; - } - - @Override - public InsertObjectRequest build() { - this.object.metadata(this.metadata.build()); - return new InsertObjectRequest<>(this); - } + static InsertObjectRequest of( + PropertiesT properties, + Function, ObjectBuilder>> fn) { + return new InsertObjectRequest<>(WriteWeaviateObject.of(ObjectBuilder.partial(fn, b -> b.properties(properties)))); } - } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/Reference.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/Reference.java index 3a4206feb..294fb588b 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/Reference.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/Reference.java @@ -8,6 +8,7 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; +import io.weaviate.client6.v1.api.collections.IWeaviateObject; import io.weaviate.client6.v1.api.collections.WeaviateObject; public record Reference(String collection, List uuids) { @@ -28,14 +29,14 @@ public static Reference uuids(String... uuids) { } /** Create references to single {@link WeaviateObject}. */ - public static Reference object(WeaviateObject object) { - return new Reference(object.collection(), object.metadata().uuid()); + public static Reference object(IWeaviateObject object) { + return new Reference(object.collection(), object.uuid()); } /** Create references to multiple {@link WeaviateObject}. */ - public static Reference[] objects(WeaviateObject... objects) { + public static Reference[] objects(IWeaviateObject... objects) { return Arrays.stream(objects) - .map(o -> new Reference(o.collection(), o.metadata().uuid())) + .map(o -> new Reference(o.collection(), o.uuid())) .toArray(Reference[]::new); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReplaceObjectRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReplaceObjectRequest.java index 2a3257d14..ea0dae5fd 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReplaceObjectRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReplaceObjectRequest.java @@ -7,67 +7,75 @@ import com.google.gson.reflect.TypeToken; import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; -import io.weaviate.client6.v1.api.collections.ObjectMetadata; import io.weaviate.client6.v1.api.collections.Vectors; -import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.internal.ObjectBuilder; import io.weaviate.client6.v1.internal.json.JSON; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; import io.weaviate.client6.v1.internal.rest.Endpoint; import io.weaviate.client6.v1.internal.rest.SimpleEndpoint; -public record ReplaceObjectRequest(WeaviateObject object) { +public record ReplaceObjectRequest(WriteWeaviateObject object) { - static final Endpoint, Void> endpoint(CollectionDescriptor collection, + static final Endpoint, Void> endpoint( + CollectionDescriptor collection, CollectionHandleDefaults defaults) { + + final var typeToken = TypeToken.getParameterized(WriteWeaviateObject.class, collection.typeToken().getType()); + return SimpleEndpoint.sideEffect( request -> "PUT", - request -> "/objects/" + collection.collectionName() + "/" + request.object.metadata().uuid(), + request -> "/objects/" + collection.collectionName() + "/" + request.object.uuid(), request -> defaults.consistencyLevel() != null ? Map.of("consistency_level", defaults.consistencyLevel()) : Collections.emptyMap(), request -> JSON.serialize( - new WriteWeaviateObject<>(request.object, defaults.tenant()), - TypeToken.getParameterized(WriteWeaviateObject.class, collection.typeToken().getType()))); + new WriteWeaviateObject<>( + request.object.uuid(), + collection.collectionName(), + defaults.tenant(), + request.object.properties(), + request.object.vectors(), + request.object.createdAt(), + request.object.lastUpdatedAt(), + request.object.references()), + typeToken)); } - public static ReplaceObjectRequest of(String collectionName, String uuid, - Function, ObjectBuilder>> fn) { - return fn.apply(new Builder<>(collectionName, uuid)).build(); + public static ReplaceObjectRequest of( + String uuid, + Function, ObjectBuilder>> fn) { + return fn.apply(new Builder<>(uuid)).build(); } - public ReplaceObjectRequest(Builder builder) { - this(builder.object.build()); + public ReplaceObjectRequest(Builder builder) { + this(builder.build()); } - public static class Builder implements ObjectBuilder> { - private final WeaviateObject.Builder object = new WeaviateObject.Builder<>(); - private final ObjectMetadata.Builder metadata = new ObjectMetadata.Builder(); + public static class Builder implements ObjectBuilder> { + private final WriteWeaviateObject.Builder object = new WriteWeaviateObject.Builder<>(); - public Builder(String collectionName, String uuid) { - this.object.collection(collectionName); - this.metadata.uuid(uuid); + public Builder(String uuid) { + this.object.uuid(uuid); } - public Builder properties(T properties) { + public Builder properties(PropertiesT properties) { this.object.properties(properties); return this; } - public Builder vectors(Vectors... vectors) { - this.metadata.vectors(vectors); + public Builder vectors(Vectors... vectors) { + this.object.vectors(vectors); return this; } - public Builder reference(String property, Reference... references) { + public Builder reference(String property, Reference... references) { this.object.reference(property, references); return this; } @Override - public ReplaceObjectRequest build() { - this.object.metadata(this.metadata.build()); - return new ReplaceObjectRequest<>(this); + public WriteWeaviateObject build() { + return this.object.build(); } } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/UpdateObjectRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/UpdateObjectRequest.java index c174e05eb..87f0a9939 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/UpdateObjectRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/UpdateObjectRequest.java @@ -7,67 +7,74 @@ import com.google.gson.reflect.TypeToken; import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; -import io.weaviate.client6.v1.api.collections.ObjectMetadata; import io.weaviate.client6.v1.api.collections.Vectors; -import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.internal.ObjectBuilder; import io.weaviate.client6.v1.internal.json.JSON; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; import io.weaviate.client6.v1.internal.rest.Endpoint; import io.weaviate.client6.v1.internal.rest.SimpleEndpoint; -public record UpdateObjectRequest(WeaviateObject object) { +public record UpdateObjectRequest(WriteWeaviateObject object) { - static final Endpoint, Void> endpoint(CollectionDescriptor collection, + static final Endpoint, Void> endpoint( + CollectionDescriptor collection, CollectionHandleDefaults defaults) { + + final var typeToken = TypeToken.getParameterized(WriteWeaviateObject.class, collection.typeToken().getType()); + return SimpleEndpoint.sideEffect( request -> "PATCH", - request -> "/objects/" + collection.collectionName() + "/" + request.object.metadata().uuid(), + request -> "/objects/" + collection.collectionName() + "/" + request.object.uuid(), request -> defaults.consistencyLevel() != null ? Map.of("consistency_level", defaults.consistencyLevel()) : Collections.emptyMap(), request -> JSON.serialize( - new WriteWeaviateObject<>(request.object, defaults.tenant()), - TypeToken.getParameterized(WriteWeaviateObject.class, collection.typeToken().getType()))); + new WriteWeaviateObject<>( + request.object.uuid(), + collection.collectionName(), + defaults.tenant(), + request.object.properties(), + request.object.vectors(), + request.object.createdAt(), + request.object.lastUpdatedAt(), + request.object.references()), + typeToken)); } - public static UpdateObjectRequest of(String collectionName, String uuid, - Function, ObjectBuilder>> fn) { - return fn.apply(new Builder<>(collectionName, uuid)).build(); + public static UpdateObjectRequest of(String uuid, + Function, ObjectBuilder>> fn) { + return fn.apply(new Builder<>(uuid)).build(); } - public UpdateObjectRequest(Builder builder) { - this(builder.object.build()); + public UpdateObjectRequest(Builder builder) { + this(builder.build()); } - public static class Builder implements ObjectBuilder> { - private final WeaviateObject.Builder object = new WeaviateObject.Builder<>(); - private final ObjectMetadata.Builder metadata = new ObjectMetadata.Builder(); + public static class Builder implements ObjectBuilder> { + private final WriteWeaviateObject.Builder object = new WriteWeaviateObject.Builder<>(); - public Builder(String collectionName, String uuid) { - this.object.collection(collectionName); - this.metadata.uuid(uuid); + public Builder(String uuid) { + this.object.uuid(uuid); } - public Builder properties(T properties) { + public Builder properties(PropertiesT properties) { this.object.properties(properties); return this; } - public Builder vectors(Vectors... vectors) { - this.metadata.vectors(vectors); + public Builder vectors(Vectors... vectors) { + this.object.vectors(vectors); return this; } - public Builder reference(String property, Reference... references) { + public Builder reference(String property, Reference... references) { this.object.reference(property, references); return this; } @Override - public UpdateObjectRequest build() { - this.object.metadata(this.metadata.build()); - return new UpdateObjectRequest<>(this); + public WriteWeaviateObject build() { + return this.object.build(); } } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClient.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClient.java index be9cb5d4e..72054c313 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClient.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClient.java @@ -6,8 +6,6 @@ import java.util.function.Function; import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; -import io.weaviate.client6.v1.api.collections.ObjectMetadata; -import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.api.collections.query.WeaviateQueryClient; import io.weaviate.client6.v1.api.collections.query.Where; import io.weaviate.client6.v1.api.collections.query.WhereOperand; @@ -45,14 +43,20 @@ public WeaviateDataClient(WeaviateDataClient c, CollectionHandleDef this.defaults = defaults; } - public WeaviateObject insert(PropertiesT properties) throws IOException { - return insert(InsertObjectRequest.of(collection.collectionName(), properties)); + public WriteWeaviateObject insert(PropertiesT properties) throws IOException { + return insert(InsertObjectRequest.of(properties)); } - public WeaviateObject insert(PropertiesT properties, - Function, ObjectBuilder>> fn) + public WriteWeaviateObject insert( + PropertiesT properties, + Function, ObjectBuilder>> fn) throws IOException { - return insert(InsertObjectRequest.of(collection.collectionName(), properties, fn)); + return insert(InsertObjectRequest.of(properties, fn)); + } + + public WriteWeaviateObject insert(InsertObjectRequest request) + throws IOException { + return this.restTransport.performRequest(request, InsertObjectRequest.endpoint(collection, defaults)); } @SafeVarargs @@ -60,12 +64,12 @@ public final InsertManyResponse insertMany(PropertiesT... objects) { return insertMany(InsertManyRequest.of(objects)); } - public InsertManyResponse insertMany(List> objects) { + public InsertManyResponse insertMany(List> objects) { return insertMany(new InsertManyRequest<>(objects)); } @SafeVarargs - public final InsertManyResponse insertMany(WeaviateObject... objects) { + public final InsertManyResponse insertMany(WriteWeaviateObject... objects) { return insertMany(Arrays.asList(objects)); } @@ -74,26 +78,23 @@ public InsertManyResponse insertMany(InsertManyRequest request) { InsertManyRequest.rpc(request.objects(), collection, defaults)); } - public WeaviateObject insert(InsertObjectRequest request) - throws IOException { - return this.restTransport.performRequest(request, InsertObjectRequest.endpoint(collection, defaults)); - } - public boolean exists(String uuid) { return this.query.byId(uuid).isPresent(); } - public void update(String uuid, + public void update( + String uuid, Function, ObjectBuilder>> fn) throws IOException { - this.restTransport.performRequest(UpdateObjectRequest.of(collection.collectionName(), uuid, fn), + this.restTransport.performRequest(UpdateObjectRequest.of(uuid, fn), UpdateObjectRequest.endpoint(collection, defaults)); } - public void replace(String uuid, + public void replace( + String uuid, Function, ObjectBuilder>> fn) throws IOException { - this.restTransport.performRequest(ReplaceObjectRequest.of(collection.collectionName(), uuid, fn), + this.restTransport.performRequest(ReplaceObjectRequest.of(uuid, fn), ReplaceObjectRequest.endpoint(collection, defaults)); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientAsync.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientAsync.java index 6aae3bb41..251536503 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientAsync.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientAsync.java @@ -8,8 +8,6 @@ import java.util.function.Function; import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; -import io.weaviate.client6.v1.api.collections.ObjectMetadata; -import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.api.collections.query.WeaviateQueryClientAsync; import io.weaviate.client6.v1.api.collections.query.Where; import io.weaviate.client6.v1.api.collections.query.WhereOperand; @@ -47,16 +45,17 @@ public WeaviateDataClientAsync(WeaviateDataClientAsync c, Collectio this.defaults = defaults; } - public CompletableFuture> insert(PropertiesT properties) { - return insert(InsertObjectRequest.of(collection.collectionName(), properties)); + public CompletableFuture> insert(PropertiesT properties) { + return insert(InsertObjectRequest.of(properties)); } - public CompletableFuture> insert(PropertiesT properties, - Function, ObjectBuilder>> fn) { - return insert(InsertObjectRequest.of(collection.collectionName(), properties, fn)); + public CompletableFuture> insert( + PropertiesT properties, + Function, ObjectBuilder>> fn) { + return insert(InsertObjectRequest.of(properties, fn)); } - public CompletableFuture> insert( + public CompletableFuture> insert( InsertObjectRequest request) { return this.restTransport.performRequestAsync(request, InsertObjectRequest.endpoint(collection, defaults)); } @@ -66,8 +65,7 @@ public final CompletableFuture insertMany(PropertiesT... obj return insertMany(InsertManyRequest.of(objects)); } - public CompletableFuture insertMany( - List> objects) { + public CompletableFuture insertMany(List> objects) { return insertMany(new InsertManyRequest<>(objects)); } @@ -80,15 +78,17 @@ public CompletableFuture exists(String uuid) { return this.query.byId(uuid).thenApply(Optional::isPresent); } - public CompletableFuture update(String uuid, + public CompletableFuture update( + String uuid, Function, ObjectBuilder>> fn) { - return this.restTransport.performRequestAsync(UpdateObjectRequest.of(collection.collectionName(), uuid, fn), + return this.restTransport.performRequestAsync(UpdateObjectRequest.of(uuid, fn), UpdateObjectRequest.endpoint(collection, defaults)); } - public CompletableFuture replace(String uuid, + public CompletableFuture replace( + String uuid, Function, ObjectBuilder>> fn) { - return this.restTransport.performRequestAsync(ReplaceObjectRequest.of(collection.collectionName(), uuid, fn), + return this.restTransport.performRequestAsync(ReplaceObjectRequest.of(uuid, fn), ReplaceObjectRequest.endpoint(collection, defaults)); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/WriteWeaviateObject.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/WriteWeaviateObject.java index a351e6667..af4d0cb68 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/WriteWeaviateObject.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/WriteWeaviateObject.java @@ -2,8 +2,10 @@ import java.io.IOException; import java.lang.reflect.ParameterizedType; +import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.function.Function; import com.google.gson.Gson; import com.google.gson.JsonArray; @@ -11,23 +13,103 @@ import com.google.gson.JsonParser; import com.google.gson.TypeAdapter; import com.google.gson.TypeAdapterFactory; +import com.google.gson.annotations.SerializedName; import com.google.gson.internal.Streams; import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; -import io.weaviate.client6.v1.api.collections.ObjectMetadata; -import io.weaviate.client6.v1.api.collections.WeaviateObject; +import io.weaviate.client6.v1.api.collections.IWeaviateObject; +import io.weaviate.client6.v1.api.collections.Vectors; +import io.weaviate.client6.v1.internal.ObjectBuilder; -public record WriteWeaviateObject

( - String collection, - P properties, - Map> references, - ObjectMetadata metadata, - String tenant) { +public record WriteWeaviateObject( + @SerializedName("id") String uuid, + @SerializedName("class") String collection, + @SerializedName("tenant") String tenant, + @SerializedName("properties") PropertiesT properties, + @SerializedName("vectors") Vectors vectors, + @SerializedName("creationTimeUnix") Long createdAt, + @SerializedName("lastUpdateTimeUnix") Long lastUpdatedAt, - WriteWeaviateObject(WeaviateObject object, String tenant) { - this(object.collection(), object.properties(), object.references(), object.metadata(), tenant); + Map> references) implements IWeaviateObject { + + public static WriteWeaviateObject of( + Function, ObjectBuilder>> fn) { + return fn.apply(new Builder<>()).build(); + } + + public WriteWeaviateObject(Builder builder) { + this( + builder.uuid, + builder.collection, + builder.tenant, + builder.properties, + builder.vectors, + null, // creationTimeUnix is read-only + null, // lastUpdateTimeUnix is read-only + builder.references); + } + + public static class Builder implements ObjectBuilder> { + private String uuid; + private String collection; + private String tenant; + private PropertiesT properties; + private Vectors vectors; + private Map> references; + + public Builder uuid(String uuid) { + this.uuid = uuid; + return this; + } + + public Builder tenant(String tenant) { + this.tenant = tenant; + return this; + } + + public Builder properties(PropertiesT properties) { + this.properties = properties; + return this; + } + + /** + * Add a reference. Calls to {@link #reference} can be chained + * to add multiple references. + */ + public Builder reference(String property, Reference... references) { + for (var ref : references) { + addReference(property, ref); + } + return this; + } + + public Builder references(Map> references) { + this.references = references; + return this; + } + + private void addReference(String property, Reference reference) { + if (!references.containsKey(property)) { + references.put(property, new ArrayList<>()); + } + references.get(property).add(reference); + } + + public Builder vectors(Vectors... vectors) { + if (this.vectors == null) { + this.vectors = vectors.length == 1 ? vectors[0] : new Vectors(vectors); + } else { + this.vectors = this.vectors.withVectors(vectors); + } + return this; + } + + @Override + public WriteWeaviateObject build() { + return new WriteWeaviateObject<>(this); + } } public static enum CustomTypeAdapterFactory implements TypeAdapterFactory { @@ -47,24 +129,21 @@ public TypeAdapter create(Gson gson, TypeToken typeToken) { var typeParams = parameterized.getActualTypeArguments(); final var propertiesType = typeParams[0]; + final TypeAdapter> delegate = (TypeAdapter>) gson + .getDelegateAdapter(this, typeToken); final var propertiesAdapter = gson.getAdapter(TypeToken.get(propertiesType)); - final var metadataAdapter = gson.getAdapter(ObjectMetadata.class); final var referencesAdapter = gson.getAdapter(Reference.class); return (TypeAdapter) new TypeAdapter>() { @Override public void write(JsonWriter out, WriteWeaviateObject value) throws IOException { - out.beginObject(); + var json = delegate.toJsonTree(value).getAsJsonObject(); + var properties = ((TypeAdapter) propertiesAdapter) + .toJsonTree(value.properties()) + .getAsJsonObject(); - out.name("class"); - out.value(value.collection()); - - out.name("properties"); - if (value.references().isEmpty()) { - ((TypeAdapter) propertiesAdapter).write(out, value.properties()); - } else { - var properties = ((TypeAdapter) propertiesAdapter).toJsonTree(value.properties()).getAsJsonObject(); + if (!value.references().isEmpty()) { for (var refEntry : value.references().entrySet()) { var beacons = new JsonArray(); for (var reference : refEntry.getValue()) { @@ -73,55 +152,40 @@ public void write(JsonWriter out, WriteWeaviateObject value) throws IOExcepti } properties.add(refEntry.getKey(), beacons); } - Streams.write(properties, out); } - // Flatten out metadata fields. - var metadata = metadataAdapter.toJsonTree(value.metadata); - for (var entry : metadata.getAsJsonObject().entrySet()) { - out.name(entry.getKey()); - Streams.write(entry.getValue(), out); - } - - out.name("tenant"); - out.value(value.tenant()); - - out.endObject(); + json.add("properties", json); + json.remove("references"); + Streams.write(json, out); } @Override public WriteWeaviateObject read(JsonReader in) throws IOException { - var builder = new WeaviateObject.Builder(); - var metadata = new ObjectMetadata.Builder(); + var json = JsonParser.parseReader(in).getAsJsonObject(); - var object = JsonParser.parseReader(in).getAsJsonObject(); - builder.collection(object.get("class").getAsString()); + var jsonProperties = json.get("properties").getAsJsonObject(); + var objectProperties = new JsonObject(); + var objectReferences = new JsonObject(); - var jsonProperties = object.get("properties").getAsJsonObject(); - var trueProperties = new JsonObject(); for (var property : jsonProperties.entrySet()) { var value = property.getValue(); - if (!value.isJsonArray()) { - trueProperties.add(property.getKey(), value); - continue; - } - var array = value.getAsJsonArray(); - var first = array.get(0); - if (first.isJsonObject() && first.getAsJsonObject().has("beacon")) { - for (var el : array) { - var beacon = referencesAdapter.fromJsonTree(el); - builder.reference(property.getKey(), (Reference) beacon); + + if (value.isJsonArray()) { + var array = value.getAsJsonArray(); + var first = array.get(0); + var isReference = first.isJsonObject() && first.getAsJsonObject().has("beacon"); + + if (isReference) { + objectReferences.add(property.getKey(), value); + continue; } } - } - builder.properties(propertiesAdapter.fromJsonTree(trueProperties)); - - metadata.uuid(object.get("id").getAsString()); - builder.metadata(metadata.build()); + objectProperties.add(property.getKey(), value); + } - var tenant = object.get("tenant"); - return new WriteWeaviateObject<>(builder.build(), tenant != null ? tenant.getAsString() : ""); + json.add("references", objectReferences); + return delegate.fromJsonTree(json); } }.nullSafe(); } From 57b5914184199a0cceaf6a55185b08e93c7e7e7e Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Wed, 19 Nov 2025 15:41:46 +0100 Subject: [PATCH 02/11] refactor: use dedicated QueryWeaviateObject in .query --- .../io/weaviate/integration/DataITest.java | 41 ++-- .../io/weaviate/integration/ORMITest.java | 4 +- .../weaviate/integration/PaginationITest.java | 12 +- .../weaviate/integration/ReferencesITest.java | 35 ++-- .../io/weaviate/integration/SearchITest.java | 64 +++--- .../v1/api/collections/IWeaviateObject.java | 5 + .../v1/api/collections/WeaviateObject.java | 195 ------------------ .../v1/api/collections/data/Reference.java | 5 +- .../data/ReplaceObjectRequest.java | 8 +- .../collections/data/UpdateObjectRequest.java | 8 +- .../api/collections/pagination/AsyncPage.java | 19 +- .../pagination/AsyncPaginator.java | 11 +- .../pagination/CursorSpliterator.java | 15 +- .../api/collections/pagination/Paginator.java | 11 +- .../query/AbstractQueryClient.java | 3 +- .../api/collections/query/QueryMetadata.java | 8 +- .../collections/query/QueryObjectGrouped.java | 4 +- .../api/collections/query/QueryResponse.java | 29 ++- .../query/QueryWeaviateObject.java | 25 +++ .../query/WeaviateQueryClient.java | 15 +- .../query/WeaviateQueryClientAsync.java | 16 +- .../client6/v1/internal/json/JSON.java | 2 - .../client6/v1/internal/json/JSONTest.java | 18 +- 23 files changed, 190 insertions(+), 363 deletions(-) create mode 100644 src/main/java/io/weaviate/client6/v1/api/collections/IWeaviateObject.java delete mode 100644 src/main/java/io/weaviate/client6/v1/api/collections/WeaviateObject.java create mode 100644 src/main/java/io/weaviate/client6/v1/api/collections/query/QueryWeaviateObject.java diff --git a/src/it/java/io/weaviate/integration/DataITest.java b/src/it/java/io/weaviate/integration/DataITest.java index 24aa43205..cb51d3e1e 100644 --- a/src/it/java/io/weaviate/integration/DataITest.java +++ b/src/it/java/io/weaviate/integration/DataITest.java @@ -20,7 +20,6 @@ import io.weaviate.client6.v1.api.collections.ReferenceProperty; import io.weaviate.client6.v1.api.collections.VectorConfig; import io.weaviate.client6.v1.api.collections.Vectors; -import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.api.collections.data.BatchReference; import io.weaviate.client6.v1.api.collections.data.DeleteManyResponse; import io.weaviate.client6.v1.api.collections.data.Reference; @@ -28,6 +27,7 @@ import io.weaviate.client6.v1.api.collections.query.Metadata.MetadataField; import io.weaviate.client6.v1.api.collections.query.QueryMetadata; import io.weaviate.client6.v1.api.collections.query.QueryReference; +import io.weaviate.client6.v1.api.collections.query.QueryWeaviateObject; import io.weaviate.client6.v1.api.collections.query.Where; import io.weaviate.containers.Container; @@ -103,7 +103,7 @@ public void testBlobData() throws IOException { cat -> cat.returnProperties("img")); Assertions.assertThat(got).get() - .extracting(WeaviateObject::properties, InstanceOfAssertFactories.MAP) + .extracting(QueryWeaviateObject::properties, InstanceOfAssertFactories.MAP) .extractingByKey("img").isEqualTo(ragdollPng); } @@ -152,10 +152,10 @@ public void testReferences_AddReplaceDelete() throws IOException { Assertions.assertThat(johnWithFriends).get() .as("friends after ADD") - .extracting(WeaviateObject::references).extracting("hasFriend") - .asInstanceOf(InstanceOfAssertFactories.list(WeaviateObject.class)) + .extracting(QueryWeaviateObject::references).extracting("hasFriend") + .asInstanceOf(InstanceOfAssertFactories.list(QueryWeaviateObject.class)) .hasSize(1) - .first().extracting(WeaviateObject::properties, InstanceOfAssertFactories.MAP) + .first().extracting(QueryWeaviateObject::properties, InstanceOfAssertFactories.MAP) .returns("albie", friend -> friend.get("name")); // Act: replace reference @@ -172,10 +172,10 @@ public void testReferences_AddReplaceDelete() throws IOException { Assertions.assertThat(johnWithFriends).get() .as("friends after REPLACE") - .extracting(WeaviateObject::references).extracting("hasFriend") - .asInstanceOf(InstanceOfAssertFactories.list(WeaviateObject.class)) + .extracting(QueryWeaviateObject::references).extracting("hasFriend") + .asInstanceOf(InstanceOfAssertFactories.list(QueryWeaviateObject.class)) .hasSize(1) - .first().extracting(WeaviateObject::properties, InstanceOfAssertFactories.MAP) + .first().extracting(QueryWeaviateObject::properties, InstanceOfAssertFactories.MAP) .returns("barbara", friend -> friend.get("name")); // Act: delete reference @@ -191,8 +191,8 @@ public void testReferences_AddReplaceDelete() throws IOException { Assertions.assertThat(johnWithFriends).get() .as("friends after DELETE") - .extracting(WeaviateObject::references).extracting("hasFriend") - .asInstanceOf(InstanceOfAssertFactories.list(WeaviateObject.class)) + .extracting(QueryWeaviateObject::references).extracting("hasFriend") + .asInstanceOf(InstanceOfAssertFactories.list(QueryWeaviateObject.class)) .isEmpty(); } @@ -218,7 +218,7 @@ public void testReplace() throws IOException { Assertions.assertThat(replacedIvanhoe).get() .as("has ONLY year property") - .extracting(WeaviateObject::properties, InstanceOfAssertFactories.MAP) + .extracting(QueryWeaviateObject::properties, InstanceOfAssertFactories.MAP) .doesNotContain(Map.entry("title", "ivanhoe")) .contains(Map.entry("year", 1819L)); } @@ -268,20 +268,20 @@ public void testUpdate() throws IOException { .satisfies(book -> { Assertions.assertThat(book) .as("has both year and title property") - .extracting(WeaviateObject::properties, InstanceOfAssertFactories.MAP) + .extracting(QueryWeaviateObject::properties, InstanceOfAssertFactories.MAP) .contains(Map.entry("title", "ivanhoe"), Map.entry("year", 1819L)); Assertions.assertThat(book) .as("has reference to Authors") - .extracting(WeaviateObject::references, InstanceOfAssertFactories.MAP) - .extractingByKey("writtenBy", InstanceOfAssertFactories.list(WeaviateObject.class)) + .extracting(QueryWeaviateObject::references, InstanceOfAssertFactories.MAP) + .extractingByKey("writtenBy", InstanceOfAssertFactories.list(QueryWeaviateObject.class)) .first() - .extracting(WeaviateObject::properties, InstanceOfAssertFactories.MAP) + .extracting(QueryWeaviateObject::properties, InstanceOfAssertFactories.MAP) .contains(Map.entry("name", "walter scott")); Assertions.assertThat(book) .as("has a vector") - .extracting(WeaviateObject::metadata) + .extracting(QueryWeaviateObject::metadata) .extracting(QueryMetadata::vectors) .returns(vector, Vectors::getDefaultSingle); }); @@ -393,9 +393,10 @@ public void testReferenceAddMany() throws IOException { Assertions.assertThat(goodburgAirports).get() .as("Goodburg has 3 airports") - .extracting(WeaviateObject::references) - .extracting(references -> references.get("hasAirports"), InstanceOfAssertFactories.list(WeaviateObject.class)) - .extracting(WeaviateObject::uuid) + .extracting(QueryWeaviateObject::references) + .extracting(references -> references.get("hasAirports"), + InstanceOfAssertFactories.list(QueryWeaviateObject.class)) + .extracting(QueryWeaviateObject::uuid) .contains(alpha, bravo, charlie); } @@ -473,7 +474,7 @@ public void testDataTypes() throws IOException { // Assert Assertions.assertThat(got).get() - .extracting(WeaviateObject::properties) + .extracting(QueryWeaviateObject::properties) .asInstanceOf(InstanceOfAssertFactories.map(String.class, Object.class)) // Most of PhoneNumber fields are only present on read and are null on write. .usingRecursiveComparison() diff --git a/src/it/java/io/weaviate/integration/ORMITest.java b/src/it/java/io/weaviate/integration/ORMITest.java index 3d066b5e5..dbe2f10bd 100644 --- a/src/it/java/io/weaviate/integration/ORMITest.java +++ b/src/it/java/io/weaviate/integration/ORMITest.java @@ -17,10 +17,10 @@ import io.weaviate.client6.v1.api.collections.CollectionConfig; import io.weaviate.client6.v1.api.collections.GeoCoordinates; import io.weaviate.client6.v1.api.collections.PhoneNumber; -import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.api.collections.annotations.Collection; import io.weaviate.client6.v1.api.collections.annotations.Property; import io.weaviate.client6.v1.api.collections.data.InsertManyResponse.InsertObject; +import io.weaviate.client6.v1.api.collections.query.QueryWeaviateObject; import io.weaviate.client6.v1.api.collections.query.Where; import io.weaviate.containers.Container; @@ -358,7 +358,7 @@ public void test_partialScan() throws IOException { // Assert Assertions.assertThat(got).get() - .extracting(WeaviateObject::properties) + .extracting(QueryWeaviateObject::properties) .returns("Dystopia", Song::title) .returns(null, Song::album) .returns(0, Song::year) diff --git a/src/it/java/io/weaviate/integration/PaginationITest.java b/src/it/java/io/weaviate/integration/PaginationITest.java index b4b02d291..269d681c0 100644 --- a/src/it/java/io/weaviate/integration/PaginationITest.java +++ b/src/it/java/io/weaviate/integration/PaginationITest.java @@ -18,10 +18,10 @@ import io.weaviate.client6.v1.api.WeaviateClient; import io.weaviate.client6.v1.api.WeaviateException; import io.weaviate.client6.v1.api.collections.Property; -import io.weaviate.client6.v1.api.collections.WeaviateMetadata; -import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.api.collections.pagination.PaginationException; import io.weaviate.client6.v1.api.collections.query.Metadata; +import io.weaviate.client6.v1.api.collections.query.QueryMetadata; +import io.weaviate.client6.v1.api.collections.query.QueryWeaviateObject; import io.weaviate.containers.Container; public class PaginationITest extends ConcurrentTest { @@ -39,7 +39,7 @@ public void testIterateAll() throws IOException { var inserted = new ArrayList(); for (var i = 0; i < count; i++) { var object = things.data.insert(Collections.emptyMap()); - inserted.add(object.metadata().uuid()); + inserted.add(object.uuid()); } assumeTrue("all objects were inserted", inserted.size() == count); @@ -47,7 +47,7 @@ public void testIterateAll() throws IOException { // Act: stream var gotStream = allThings.stream() - .map(WeaviateObject::metadata).map(WeaviateMetadata::uuid).toList(); + .map(QueryWeaviateObject::metadata).map(QueryMetadata::uuid).toList(); // Assert Assertions.assertThat(gotStream) @@ -84,7 +84,7 @@ public void testResumePagination() throws IOException { var inserted = new ArrayList(); for (var i = 0; i < count; i++) { var object = things.data.insert(Collections.emptyMap()); - inserted.add(object.metadata().uuid()); + inserted.add(object.uuid()); } // Iterate over first 5 objects @@ -114,7 +114,7 @@ public void testWithQueryOptions() throws IOException { var inserted = new ArrayList(); for (var i = 0; i < count; i++) { var object = things.data.insert(Collections.emptyMap()); - inserted.add(object.metadata().uuid()); + inserted.add(object.uuid()); } // Act / Assert diff --git a/src/it/java/io/weaviate/integration/ReferencesITest.java b/src/it/java/io/weaviate/integration/ReferencesITest.java index 53a36a2c1..41ca8e2c3 100644 --- a/src/it/java/io/weaviate/integration/ReferencesITest.java +++ b/src/it/java/io/weaviate/integration/ReferencesITest.java @@ -11,12 +11,11 @@ import io.weaviate.ConcurrentTest; import io.weaviate.client6.v1.api.WeaviateClient; -import io.weaviate.client6.v1.api.collections.ObjectMetadata; import io.weaviate.client6.v1.api.collections.Property; import io.weaviate.client6.v1.api.collections.ReferenceProperty; -import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.api.collections.data.Reference; import io.weaviate.client6.v1.api.collections.query.QueryReference; +import io.weaviate.client6.v1.api.collections.query.QueryWeaviateObject; import io.weaviate.containers.Container; /** @@ -74,7 +73,7 @@ public void testReferences() throws IOException { Map.of("name", "Alex"), opt -> opt .reference("hasAwards", Reference.uuids( - grammy_1.metadata().uuid(), oscar_1.metadata().uuid())) + grammy_1.uuid(), oscar_1.uuid())) .reference("hasAwards", Reference.objects(grammy_2, oscar_2))); // Act: add one more reference @@ -91,7 +90,7 @@ public void testReferences() throws IOException { .extracting(ReferenceProperty::dataTypes, InstanceOfAssertFactories.list(String.class)) .containsOnly(nsMovies); - var gotAlex = artists.query.byId(alex.metadata().uuid(), + var gotAlex = artists.query.byId(alex.uuid(), opt -> opt.returnReferences( QueryReference.multi("hasAwards", nsOscar), QueryReference.multi("hasAwards", nsGrammy))); @@ -99,12 +98,12 @@ public void testReferences() throws IOException { Assertions.assertThat(gotAlex).get() .as("Artists: fetch by id including hasAwards references") - // Cast references to Map> - .extracting(WeaviateObject::references, InstanceOfAssertFactories.map(String.class, List.class)) + // Cast references to Map> + .extracting(QueryWeaviateObject::references, InstanceOfAssertFactories.map(String.class, List.class)) .as("hasAwards object reference").extractingByKey("hasAwards") - .asInstanceOf(InstanceOfAssertFactories.list(WeaviateObject.class)) + .asInstanceOf(InstanceOfAssertFactories.list(QueryWeaviateObject.class)) - .extracting(object -> ((ObjectMetadata) object.metadata()).uuid()) + .extracting(object -> object.uuid()) .containsOnly( // INVESTIGATE: When references to 2+ collections are requested, // seems to Weaviate only return references to the first one in the list. @@ -112,7 +111,7 @@ public void testReferences() throws IOException { // so the latter will not be in the response. // // grammy_1.metadata().id(), grammy_2.metadata().id(), - oscar_1.metadata().uuid(), oscar_2.metadata().uuid()); + oscar_1.uuid(), oscar_2.uuid()); } @Test @@ -155,7 +154,7 @@ public void testNestedReferences() throws IOException { .reference("hasAwards", Reference.objects(grammy_1))); // Assert: fetch nested references - var gotAlex = artists.query.byId(alex.metadata().uuid(), + var gotAlex = artists.query.byId(alex.uuid(), opt -> opt.returnReferences( QueryReference.single("hasAwards", ref -> ref @@ -166,20 +165,20 @@ public void testNestedReferences() throws IOException { Assertions.assertThat(gotAlex).get() .as("Artists: fetch by id including nested references") - // Cast references to Map> - .extracting(WeaviateObject::references, InstanceOfAssertFactories.map(String.class, List.class)) + // Cast references to Map> + .extracting(QueryWeaviateObject::references, InstanceOfAssertFactories.map(String.class, List.class)) .as("hasAwards object reference").extractingByKey("hasAwards") - .asInstanceOf(InstanceOfAssertFactories.list(WeaviateObject.class)) + .asInstanceOf(InstanceOfAssertFactories.list(QueryWeaviateObject.class)) .hasSize(1).allSatisfy(award -> Assertions.assertThat(award) - .returns(grammy_1.metadata().uuid(), grammy -> ((ObjectMetadata) grammy.metadata()).uuid()) + .returns(grammy_1.uuid(), grammy -> grammy.uuid()) - // Cast references to Map> - .extracting(WeaviateObject::references, InstanceOfAssertFactories.map(String.class, List.class)) + // Cast references to Map> + .extracting(QueryWeaviateObject::references, InstanceOfAssertFactories.map(String.class, List.class)) .as("presentedBy object reference").extractingByKey("presentedBy") - .asInstanceOf(InstanceOfAssertFactories.list(WeaviateObject.class)) + .asInstanceOf(InstanceOfAssertFactories.list(QueryWeaviateObject.class)) - .hasSize(1).extracting(WeaviateObject::properties) + .hasSize(1).extracting(QueryWeaviateObject::properties) .allSatisfy(properties -> Assertions.assertThat(properties) .asInstanceOf(InstanceOfAssertFactories.map(String.class, Object.class)) .containsEntry("ceo", "Harvy Mason"))); diff --git a/src/it/java/io/weaviate/integration/SearchITest.java b/src/it/java/io/weaviate/integration/SearchITest.java index 346a8b2a3..5ec7d2888 100644 --- a/src/it/java/io/weaviate/integration/SearchITest.java +++ b/src/it/java/io/weaviate/integration/SearchITest.java @@ -19,14 +19,13 @@ import io.weaviate.ConcurrentTest; import io.weaviate.client6.v1.api.WeaviateApiException; import io.weaviate.client6.v1.api.WeaviateClient; -import io.weaviate.client6.v1.api.collections.ObjectMetadata; import io.weaviate.client6.v1.api.collections.Property; import io.weaviate.client6.v1.api.collections.ReferenceProperty; import io.weaviate.client6.v1.api.collections.VectorConfig; import io.weaviate.client6.v1.api.collections.Vectors; import io.weaviate.client6.v1.api.collections.WeaviateMetadata; -import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.api.collections.data.Reference; +import io.weaviate.client6.v1.api.collections.data.WriteWeaviateObject; import io.weaviate.client6.v1.api.collections.generate.GenerativeObject; import io.weaviate.client6.v1.api.collections.generate.TaskOutput; import io.weaviate.client6.v1.api.collections.generative.DummyGenerative; @@ -34,6 +33,7 @@ import io.weaviate.client6.v1.api.collections.query.Metadata; import io.weaviate.client6.v1.api.collections.query.QueryMetadata; import io.weaviate.client6.v1.api.collections.query.QueryResponseGroup; +import io.weaviate.client6.v1.api.collections.query.QueryWeaviateObject; import io.weaviate.client6.v1.api.collections.query.SortBy; import io.weaviate.client6.v1.api.collections.query.Target; import io.weaviate.client6.v1.api.collections.query.Where; @@ -128,7 +128,7 @@ private static Map populateTest(int n) throws IOException { .uuid(randomUUID()) .vectors(Vectors.of(VECTOR_INDEX, vector))); - created.put(object.metadata().uuid(), vector); + created.put(object.uuid(), vector); } return created; @@ -162,11 +162,11 @@ public void testNearText() throws IOException { opt -> opt .distance(0.9f) .moveTo(.98f, to -> to.concepts("tropical")) - .moveAway(.4f, away -> away.uuids(submarine.metadata().uuid())) + .moveAway(.4f, away -> away.uuids(submarine.uuid())) .returnProperties("title")); Assertions.assertThat(result.objects()).hasSize(2) - .extracting(WeaviateObject::properties).allSatisfy( + .extracting(QueryWeaviateObject::properties).allSatisfy( properties -> Assertions.assertThat(properties) .allSatisfy((_k, v) -> Assertions.assertThat((String) v).contains("Jungle"))); } @@ -204,8 +204,8 @@ public void testNearText_groupBy() throws IOException { Assertions.assertThat(result.groups()).hasSize(2) .containsOnlyKeys( - "weaviate://localhost/%s/%s".formatted(nsArtists, beatles.metadata().uuid()), - "weaviate://localhost/%s/%s".formatted(nsArtists, ccr.metadata().uuid())); + "weaviate://localhost/%s/%s".formatted(nsArtists, beatles.uuid()), + "weaviate://localhost/%s/%s".formatted(nsArtists, ccr.uuid())); } @Test @@ -229,7 +229,7 @@ public void testNearImage() throws IOException { opt -> opt.returnProperties("breed")); Assertions.assertThat(got.objects()).hasSize(1).first() - .extracting(WeaviateObject::properties, InstanceOfAssertFactories.MAP) + .extracting(QueryWeaviateObject::properties, InstanceOfAssertFactories.MAP) .extractingByKey("breed").isEqualTo("ragdoll"); } @@ -261,9 +261,9 @@ public void testFetchObjectsWithFilters() throws IOException { Assertions.assertThat(got.objects()) .extracting(hat -> hat.metadata().uuid()) .containsOnly( - redHat.metadata().uuid(), - greenHat.metadata().uuid(), - hugeHat.metadata().uuid()); + redHat.uuid(), + greenHat.uuid(), + hugeHat.uuid()); } @@ -288,7 +288,7 @@ public void testFetchObjectsWithSort() throws Exception { Assertions.assertThat(asc.objects()) .as("value asc") .hasSize(3) - .extracting(WeaviateObject::properties) + .extracting(QueryWeaviateObject::properties) .extracting(object -> object.get("value")) .containsExactly(1L, 2L, 3L); @@ -299,7 +299,7 @@ public void testFetchObjectsWithSort() throws Exception { Assertions.assertThat(desc.objects()) .as("value desc") .hasSize(3) - .extracting(WeaviateObject::properties) + .extracting(QueryWeaviateObject::properties) .extracting(object -> object.get("value")) .containsExactly(3L, 2L, 1L); } @@ -325,8 +325,8 @@ public void testBm25() throws IOException, InterruptedException, ExecutionExcept Assertions.assertThat(dollarWorlds.objects()) .hasSize(1) - .extracting(WeaviateObject::metadata).extracting(QueryMetadata::uuid) - .containsOnly(want.metadata().uuid()); + .extracting(QueryWeaviateObject::metadata).extracting(QueryMetadata::uuid) + .containsOnly(want.uuid()); } /** @@ -357,8 +357,8 @@ public void testBm25_async() throws Exception, InterruptedException, ExecutionEx Assertions.assertThat(dollarWorlds.objects()) .hasSize(1) - .extracting(WeaviateObject::metadata).extracting(QueryMetadata::uuid) - .containsOnly(want.metadata().uuid()); + .extracting(QueryWeaviateObject::metadata).extracting(QueryMetadata::uuid) + .containsOnly(want.uuid()); } } @@ -381,14 +381,14 @@ public void testNearObject() throws IOException { animals.data.insert(Map.of("kind", "dolphin")); // Act - var terrestrial = animals.query.nearObject(cat.metadata().uuid(), + var terrestrial = animals.query.nearObject(cat.uuid(), q -> q.excludeSelf().limit(1)); // Assert Assertions.assertThat(terrestrial.objects()) .hasSize(1) - .extracting(WeaviateObject::metadata).extracting(WeaviateMetadata::uuid) - .containsOnly(lion.metadata().uuid()); + .extracting(QueryWeaviateObject::metadata).extracting(WeaviateMetadata::uuid) + .containsOnly(lion.uuid()); } @Test @@ -414,8 +414,8 @@ public void testHybrid() throws IOException { // Assert Assertions.assertThat(winterSport.objects()) .hasSize(1) - .extracting(WeaviateObject::metadata).extracting(WeaviateMetadata::uuid) - .containsOnly(skiing.metadata().uuid()); + .extracting(QueryWeaviateObject::metadata).extracting(WeaviateMetadata::uuid) + .containsOnly(skiing.uuid()); var first = winterSport.objects().get(0); Assertions.assertThat(first.metadata().score()) @@ -484,7 +484,7 @@ public void test_includeVectors() throws IOException { // Assert Assertions.assertThat(got).get() - .extracting(WeaviateObject::vectors) + .extracting(QueryWeaviateObject::vectors) .returns(true, v -> v.contains("v1")) .returns(true, v -> v.contains("v2")) .returns(false, v -> v.contains("v3")); @@ -513,7 +513,7 @@ public void testMetadataAll() throws IOException { // Assert var metadataHybrid = Assertions.assertThat(gotHybrid.objects()) .hasSize(1) - .extracting(WeaviateObject::metadata) + .extracting(QueryWeaviateObject::metadata) .first().actual(); Assertions.assertThat(metadataHybrid.uuid()).as("uuid").isNotNull().isEqualTo(frisbee.uuid()); @@ -524,7 +524,7 @@ public void testMetadataAll() throws IOException { var metadataNearText = Assertions.assertThat(gotNearText.objects()) .hasSize(1) - .extracting(WeaviateObject::metadata) + .extracting(QueryWeaviateObject::metadata) .first().actual(); Assertions.assertThat(metadataNearText.uuid()).as("uuid").isNotNull().isEqualTo(frisbee.uuid()); @@ -552,12 +552,10 @@ public void testNearVector_targetVectors() throws IOException { Vectors.of("v2d", new float[][] { { 1, 2, 3 }, { 1, 2, 3 } }))); var thing456 = things.data.insertMany(List.of( - WeaviateObject.of(thing -> thing - .metadata(ObjectMetadata.of( - meta -> meta - .vectors( - Vectors.of("v1d", new float[] { 4, 5, 6 }), - Vectors.of("v2d", new float[][] { { 4, 5, 6 }, { 4, 5, 6 } }))))))); + WriteWeaviateObject.of(thing -> thing + .vectors( + Vectors.of("v1d", new float[] { 4, 5, 6 }), + Vectors.of("v2d", new float[][] { { 4, 5, 6 }, { 4, 5, 6 } }))))); Assertions.assertThat(thing456.errors()).as("insert many").isEmpty(); // Act @@ -566,7 +564,7 @@ public void testNearVector_targetVectors() throws IOException { q -> q.limit(1)); Assertions.assertThat(got123.objects()) .as("search v1d") - .hasSize(1).extracting(WeaviateObject::uuid) + .hasSize(1).extracting(QueryWeaviateObject::uuid) .containsExactly(thing123.uuid()); var got456 = things.query.nearVector( @@ -574,7 +572,7 @@ public void testNearVector_targetVectors() throws IOException { q -> q.limit(1)); Assertions.assertThat(got456.objects()) .as("search v2d") - .hasSize(1).extracting(WeaviateObject::uuid) + .hasSize(1).extracting(QueryWeaviateObject::uuid) .containsExactly(thing456.uuids().get(0)); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/IWeaviateObject.java b/src/main/java/io/weaviate/client6/v1/api/collections/IWeaviateObject.java new file mode 100644 index 000000000..8e52285be --- /dev/null +++ b/src/main/java/io/weaviate/client6/v1/api/collections/IWeaviateObject.java @@ -0,0 +1,5 @@ +package io.weaviate.client6.v1.api.collections; + +public interface IWeaviateObject { + String uuid(); +} diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/WeaviateObject.java b/src/main/java/io/weaviate/client6/v1/api/collections/WeaviateObject.java deleted file mode 100644 index 3180cf2e7..000000000 --- a/src/main/java/io/weaviate/client6/v1/api/collections/WeaviateObject.java +++ /dev/null @@ -1,195 +0,0 @@ -package io.weaviate.client6.v1.api.collections; - -import java.io.IOException; -import java.lang.reflect.ParameterizedType; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Function; - -import com.google.gson.Gson; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.TypeAdapter; -import com.google.gson.TypeAdapterFactory; -import com.google.gson.internal.Streams; -import com.google.gson.reflect.TypeToken; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; - -import io.weaviate.client6.v1.internal.ObjectBuilder; - -public record WeaviateObject( - String collection, - P properties, - Map> references, - M metadata) { - - /** Shorthand for accesing objects's UUID from metadata. */ - public String uuid() { - return metadata.uuid(); - } - - /** Shorthand for accesing objects's vectors from metadata. */ - public Vectors vectors() { - return metadata.vectors(); - } - - public static WeaviateObject of( - Function, ObjectBuilder>> fn) { - return fn.apply(new Builder<>()).build(); - } - - public WeaviateObject(Builder builder) { - this(builder.collectionName, builder.properties, builder.references, builder.metadata); - } - - public static class Builder implements ObjectBuilder> { - private String collectionName; - private P properties; - private Map> references = new HashMap<>(); - private M metadata; - - /** Set the name of the collection his object belongs to. */ - public final Builder collection(String collectionName) { - this.collectionName = collectionName; - return this; - } - - /** Add object properties. */ - public final Builder properties(P properties) { - this.properties = properties; - return this; - } - - /** - * Add a reference. Calls to {@link #reference} can be chained - * to add multiple references. - */ - @SafeVarargs - public final Builder reference(String property, R... references) { - for (var ref : references) { - addReference(property, ref); - } - return this; - } - - private final void addReference(String property, R reference) { - if (!references.containsKey(property)) { - references.put(property, new ArrayList<>()); - } - references.get(property).add(reference); - } - - public Builder references(Map> references) { - this.references = references; - return this; - } - - public Builder metadata(M metadata) { - this.metadata = metadata; - return this; - } - - @Override - public WeaviateObject build() { - return new WeaviateObject<>(this); - } - } - - public static enum CustomTypeAdapterFactory implements TypeAdapterFactory { - INSTANCE; - - @SuppressWarnings("unchecked") - @Override - public TypeAdapter create(Gson gson, TypeToken typeToken) { - var type = typeToken.getType(); - var rawType = typeToken.getRawType(); - if (rawType != WeaviateObject.class || - !(type instanceof ParameterizedType parameterized) - || parameterized.getActualTypeArguments().length < 3) { - return null; - } - - var typeParams = parameterized.getActualTypeArguments(); - final var propertiesType = typeParams[0]; - final var referencesType = typeParams[1]; - final var metadataType = typeParams[2]; - - final var propertiesAdapter = gson.getAdapter(TypeToken.get(propertiesType)); - final var metadataAdapter = gson.getAdapter(TypeToken.get(metadataType)); - final var referencesAdapter = gson.getAdapter(TypeToken.get(referencesType)); - - return (TypeAdapter) new TypeAdapter>() { - - @Override - public void write(JsonWriter out, WeaviateObject value) throws IOException { - out.beginObject(); - - out.name("class"); - out.value(value.collection()); - - out.name("properties"); - if (value.references().isEmpty()) { - ((TypeAdapter) propertiesAdapter).write(out, value.properties()); - } else { - var properties = ((TypeAdapter) propertiesAdapter).toJsonTree(value.properties()).getAsJsonObject(); - for (var refEntry : value.references().entrySet()) { - var beacons = new JsonArray(); - for (var reference : (List) refEntry.getValue()) { - var beacon = ((TypeAdapter) referencesAdapter).toJsonTree(reference); - beacons.add(beacon); - } - properties.add(refEntry.getKey(), beacons); - } - Streams.write(properties, out); - } - - // Flatten out metadata fields. - var metadata = ((TypeAdapter) metadataAdapter).toJsonTree(value.metadata); - for (var entry : metadata.getAsJsonObject().entrySet()) { - out.name(entry.getKey()); - Streams.write(entry.getValue(), out); - } - out.endObject(); - } - - @Override - public WeaviateObject read(JsonReader in) throws IOException { - var builder = new WeaviateObject.Builder<>(); - var metadata = new ObjectMetadata.Builder(); - - var object = JsonParser.parseReader(in).getAsJsonObject(); - builder.collection(object.get("class").getAsString()); - - var jsonProperties = object.get("properties").getAsJsonObject(); - var trueProperties = new JsonObject(); - for (var property : jsonProperties.entrySet()) { - var value = property.getValue(); - if (!value.isJsonArray()) { - trueProperties.add(property.getKey(), value); - continue; - } - var array = value.getAsJsonArray(); - var first = array.get(0); - if (first.isJsonObject() && first.getAsJsonObject().has("beacon")) { - for (var el : array) { - var beacon = ((TypeAdapter) referencesAdapter).fromJsonTree(el); - builder.reference(property.getKey(), beacon); - } - } - } - - builder.properties(propertiesAdapter.fromJsonTree(trueProperties)); - - metadata.uuid(object.get("id").getAsString()); - builder.metadata(metadata.build()); - - return builder.build(); - } - }.nullSafe(); - } - } -} diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/Reference.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/Reference.java index 294fb588b..302b90866 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/Reference.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/Reference.java @@ -9,7 +9,6 @@ import com.google.gson.stream.JsonWriter; import io.weaviate.client6.v1.api.collections.IWeaviateObject; -import io.weaviate.client6.v1.api.collections.WeaviateObject; public record Reference(String collection, List uuids) { @@ -28,12 +27,12 @@ public static Reference uuids(String... uuids) { return new Reference(null, Arrays.asList(uuids)); } - /** Create references to single {@link WeaviateObject}. */ + /** Create references to single {@link IWeaviateObject}. */ public static Reference object(IWeaviateObject object) { return new Reference(object.collection(), object.uuid()); } - /** Create references to multiple {@link WeaviateObject}. */ + /** Create references to multiple {@link IWeaviateObject}. */ public static Reference[] objects(IWeaviateObject... objects) { return Arrays.stream(objects) .map(o -> new Reference(o.collection(), o.uuid())) diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReplaceObjectRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReplaceObjectRequest.java index ea0dae5fd..d3d1ec31f 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReplaceObjectRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReplaceObjectRequest.java @@ -48,10 +48,10 @@ public static ReplaceObjectRequest of( } public ReplaceObjectRequest(Builder builder) { - this(builder.build()); + this(builder.object.build()); } - public static class Builder implements ObjectBuilder> { + public static class Builder implements ObjectBuilder> { private final WriteWeaviateObject.Builder object = new WriteWeaviateObject.Builder<>(); public Builder(String uuid) { @@ -74,8 +74,8 @@ public Builder reference(String property, Reference... references) } @Override - public WriteWeaviateObject build() { - return this.object.build(); + public ReplaceObjectRequest build() { + return new ReplaceObjectRequest<>(this); } } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/UpdateObjectRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/UpdateObjectRequest.java index 87f0a9939..3368468a7 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/UpdateObjectRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/UpdateObjectRequest.java @@ -47,10 +47,10 @@ public static UpdateObjectRequest of(String uuid, } public UpdateObjectRequest(Builder builder) { - this(builder.build()); + this(builder.object.build()); } - public static class Builder implements ObjectBuilder> { + public static class Builder implements ObjectBuilder> { private final WriteWeaviateObject.Builder object = new WriteWeaviateObject.Builder<>(); public Builder(String uuid) { @@ -73,8 +73,8 @@ public Builder reference(String property, Reference... references) } @Override - public WriteWeaviateObject build() { - return this.object.build(); + public UpdateObjectRequest build() { + return new UpdateObjectRequest<>(this); } } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPage.java b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPage.java index 691b8bad6..807e6a608 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPage.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPage.java @@ -7,32 +7,31 @@ import java.util.concurrent.CompletableFuture; import java.util.function.BiFunction; -import io.weaviate.client6.v1.api.collections.WeaviateObject; -import io.weaviate.client6.v1.api.collections.query.QueryMetadata; +import io.weaviate.client6.v1.api.collections.query.QueryWeaviateObject; -public final class AsyncPage implements Iterable> { +public final class AsyncPage implements Iterable> { private final int pageSize; - private final BiFunction>>> fetch; + private final BiFunction>>> fetch; private final String cursor; - private List> currentPage = new ArrayList<>(); + private List> currentPage = new ArrayList<>(); AsyncPage(String cursor, int pageSize, - BiFunction>>> fetch) { + BiFunction>>> fetch) { this.cursor = cursor; this.pageSize = pageSize; this.fetch = fetch; } AsyncPage(String cursor, int pageSize, - BiFunction>>> fetch, - List> currentPage) { + BiFunction>>> fetch, + List> currentPage) { this(cursor, pageSize, fetch); this.currentPage = Collections.unmodifiableList(currentPage); } - List> items() { + List> items() { return currentPage; } @@ -69,7 +68,7 @@ public CompletableFuture> fetchNextPage() { } @Override - public Iterator> iterator() { + public Iterator> iterator() { return currentPage.iterator(); } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPaginator.java b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPaginator.java index 972f07a4f..1163965bb 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPaginator.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPaginator.java @@ -5,12 +5,11 @@ import java.util.function.Consumer; import java.util.function.Function; -import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.api.collections.query.FetchObjects; import io.weaviate.client6.v1.api.collections.query.Metadata; -import io.weaviate.client6.v1.api.collections.query.QueryMetadata; import io.weaviate.client6.v1.api.collections.query.QueryReference; import io.weaviate.client6.v1.api.collections.query.QueryResponse; +import io.weaviate.client6.v1.api.collections.query.QueryWeaviateObject; import io.weaviate.client6.v1.api.collections.query.WeaviateQueryClientAsync; import io.weaviate.client6.v1.internal.ObjectBuilder; @@ -46,25 +45,25 @@ public AsyncPaginator(Builder builder) { this.resultSet = builder.prefetch ? rs.fetchNextPage() : CompletableFuture.completedFuture(rs); } - public CompletableFuture forEach(Consumer> action) { + public CompletableFuture forEach(Consumer> action) { return resultSet .thenCompose(rs -> rs.isEmpty() ? rs.fetchNextPage() : CompletableFuture.completedFuture(rs)) .thenCompose(processEachAndAdvance(action)); } - public CompletableFuture forPage(Consumer>> action) { + public CompletableFuture forPage(Consumer>> action) { return resultSet .thenCompose(rs -> rs.isEmpty() ? rs.fetchNextPage() : CompletableFuture.completedFuture(rs)) .thenCompose(processPageAndAdvance(action)); } private static Function, CompletableFuture> processEachAndAdvance( - Consumer> action) { + Consumer> action) { return processAndAdvanceFunc(rs -> rs.forEach(action)); } private static Function, CompletableFuture> processPageAndAdvance( - Consumer>> action) { + Consumer>> action) { return processAndAdvanceFunc(rs -> action.accept(rs.items())); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/CursorSpliterator.java b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/CursorSpliterator.java index 3b0335d88..ddc0b2574 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/CursorSpliterator.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/CursorSpliterator.java @@ -7,27 +7,26 @@ import java.util.function.BiFunction; import java.util.function.Consumer; -import io.weaviate.client6.v1.api.collections.WeaviateObject; -import io.weaviate.client6.v1.api.collections.query.QueryMetadata; +import io.weaviate.client6.v1.api.collections.query.QueryWeaviateObject; -public class CursorSpliterator implements Spliterator> { +public class CursorSpliterator implements Spliterator> { private final int pageSize; - private final BiFunction>> fetch; + private final BiFunction>> fetch; // Spliterators do not promise thread-safety, so there's no mechanism // to protect access to its internal state. private String cursor; - private Iterator> currentPage = Collections.emptyIterator(); + private Iterator> currentPage = Collections.emptyIterator(); public CursorSpliterator(String cursor, int pageSize, - BiFunction>> fetch) { + BiFunction>> fetch) { this.cursor = cursor; this.pageSize = pageSize; this.fetch = fetch; } @Override - public boolean tryAdvance(Consumer> action) { + public boolean tryAdvance(Consumer> action) { // Happy path: there are remaining objects in the current page. if (currentPage.hasNext()) { action.accept(currentPage.next()); @@ -54,7 +53,7 @@ public boolean tryAdvance(Consumer> trySplit() { + public Spliterator> trySplit() { // Do not support splitting just now; return null; } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/Paginator.java b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/Paginator.java index b5de3a370..089256c24 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/Paginator.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/Paginator.java @@ -8,16 +8,15 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; -import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.api.collections.query.FetchObjects; import io.weaviate.client6.v1.api.collections.query.Metadata; -import io.weaviate.client6.v1.api.collections.query.QueryMetadata; import io.weaviate.client6.v1.api.collections.query.QueryReference; +import io.weaviate.client6.v1.api.collections.query.QueryWeaviateObject; import io.weaviate.client6.v1.api.collections.query.WeaviateQueryClient; import io.weaviate.client6.v1.api.collections.query.Where; import io.weaviate.client6.v1.internal.ObjectBuilder; -public class Paginator implements Iterable> { +public class Paginator implements Iterable> { static final int DEFAULT_PAGE_SIZE = 100; private final WeaviateQueryClient query; @@ -26,15 +25,15 @@ public class Paginator implements Iterable> iterator() { + public Iterator> iterator() { return Spliterators.iterator(spliterator()); } - public Stream> stream() { + public Stream> stream() { return StreamSupport.stream(spliterator(), false); } - public Spliterator> spliterator() { + public Spliterator> spliterator() { return new CursorSpliterator(cursor, pageSize, (after, limit) -> { var fn = ObjectBuilder.partial(queryOptions, q -> q.after(after).limit(limit)); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/AbstractQueryClient.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/AbstractQueryClient.java index 99ee83fd6..422cd709e 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/AbstractQueryClient.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/AbstractQueryClient.java @@ -7,7 +7,6 @@ import io.weaviate.client6.v1.api.WeaviateApiException; import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; -import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.internal.ObjectBuilder; import io.weaviate.client6.v1.internal.grpc.GrpcTransport; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; @@ -73,7 +72,7 @@ public SingleT byId(String uuid, Function> fn) * @param response Query response. * @return An object from the list or empty {@link Optional}. */ - protected final Optional> optionalFirst(QueryResponse response) { + protected final

Optional> optionalFirst(QueryResponse

response) { return response == null || response.objects().isEmpty() ? Optional.empty() : Optional.ofNullable(response.objects().get(0)); 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 25f8f676e..03896895d 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 @@ -49,8 +49,12 @@ final Builder uuid(String uuid) { return this; } - final Builder vectors(Vectors vectors) { - this.vectors = vectors; + public Builder vectors(Vectors... vectors) { + if (this.vectors == null) { + this.vectors = vectors.length == 1 ? vectors[0] : new Vectors(vectors); + } else { + this.vectors = this.vectors.withVectors(vectors); + } return this; } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryObjectGrouped.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryObjectGrouped.java index f98014af1..562d03780 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryObjectGrouped.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryObjectGrouped.java @@ -1,7 +1,5 @@ package io.weaviate.client6.v1.api.collections.query; -import io.weaviate.client6.v1.api.collections.WeaviateObject; - public record QueryObjectGrouped( /** Object properties. */ PropertiesT properties, @@ -10,7 +8,7 @@ public record QueryObjectGrouped( /** Name of the group that the object belongs to. */ String belongsToGroup) { - QueryObjectGrouped(WeaviateObject object, + QueryObjectGrouped(QueryWeaviateObject object, String belongsToGroup) { this(object.properties(), object.metadata(), belongsToGroup); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryResponse.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryResponse.java index 98889c492..49643e0fa 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryResponse.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryResponse.java @@ -7,10 +7,8 @@ import java.util.stream.Stream; import io.weaviate.client6.v1.api.collections.GeoCoordinates; -import io.weaviate.client6.v1.api.collections.ObjectMetadata; import io.weaviate.client6.v1.api.collections.PhoneNumber; import io.weaviate.client6.v1.api.collections.Vectors; -import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.internal.DateUtil; import io.weaviate.client6.v1.internal.grpc.ByteStringUtil; import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoProperties; @@ -19,7 +17,7 @@ import io.weaviate.client6.v1.internal.orm.PropertiesBuilder; public record QueryResponse( - List> objects) { + List> objects) { static QueryResponse unmarshal(WeaviateProtoSearchGet.SearchReply reply, CollectionDescriptor collection) { @@ -32,7 +30,7 @@ static QueryResponse unmarshal(WeaviateProtoSearchGet return new QueryResponse<>(objects); } - public static WeaviateObject unmarshalResultObject( + public static QueryWeaviateObject unmarshalResultObject( WeaviateProtoSearchGet.PropertiesResult propertiesResult, WeaviateProtoSearchGet.MetadataResult metadataResult, CollectionDescriptor collection) { @@ -59,11 +57,11 @@ public static WeaviateObject u if (metadataResult.getExplainScorePresent()) { metadata.explainScore(metadataResult.getExplainScore()); } - return new WeaviateObject<>(collection.collectionName(), object.properties(), object.references(), + return new QueryWeaviateObject<>(collection.collectionName(), object.properties(), object.references(), metadata.build()); } - static WeaviateObject unmarshalWithReferences( + static QueryWeaviateObject unmarshalWithReferences( WeaviateProtoSearchGet.PropertiesResult propertiesResult, WeaviateProtoSearchGet.MetadataResult metadataResult, CollectionDescriptor descriptor) { @@ -78,14 +76,14 @@ static WeaviateObject unmarsh // I.e. { "ref": A-1 } , { "ref": B-1 } => { "ref": [A-1, B-1] } var referenceProperties = propertiesResult.getRefPropsList() .stream().reduce( - new HashMap>(), + new HashMap>>(), (map, ref) -> { var refObjects = ref.getPropertiesList().stream() .map(property -> { var reference = unmarshalWithReferences( property, property.getMetadata(), CollectionDescriptor.ofMap(property.getTargetCollection())); - return (Object) new WeaviateObject<>( + return new QueryWeaviateObject<>( reference.collection(), (Object) reference.properties(), reference.references(), @@ -110,9 +108,9 @@ static WeaviateObject unmarsh return left; }); - ObjectMetadata metadata = null; + QueryMetadata metadata = null; if (metadataResult != null) { - var metadataBuilder = new ObjectMetadata.Builder() + var metadataBuilder = new QueryMetadata.Builder() .uuid(metadataResult.getId()); var vectors = new Vectors[metadataResult.getVectorsList().size()]; @@ -135,12 +133,11 @@ static WeaviateObject unmarsh metadata = metadataBuilder.build(); } - var obj = new WeaviateObject.Builder() - .collection(descriptor.collectionName()) - .properties(properties.build()) - .references(referenceProperties) - .metadata(metadata); - return obj.build(); + return new QueryWeaviateObject<>( + descriptor.collectionName(), + properties.build(), + referenceProperties, + metadata); } static void setProperty(String property, WeaviateProtoProperties.Value value, diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryWeaviateObject.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryWeaviateObject.java new file mode 100644 index 000000000..1f0ad5f58 --- /dev/null +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryWeaviateObject.java @@ -0,0 +1,25 @@ +package io.weaviate.client6.v1.api.collections.query; + +import java.util.List; +import java.util.Map; + +import io.weaviate.client6.v1.api.collections.IWeaviateObject; +import io.weaviate.client6.v1.api.collections.Vectors; + +public record QueryWeaviateObject( + String collection, + PropertiesT properties, + Map>> references, + QueryMetadata metadata) implements IWeaviateObject { + + /** Shorthand for accesing objects's UUID from metadata. */ + @Override + public String uuid() { + return metadata.uuid(); + } + + /** Shorthand for accesing objects's vectors from metadata. */ + public Vectors vectors() { + return metadata.vectors(); + } +} diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClient.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClient.java index d88588450..4bcfdb9c0 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClient.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClient.java @@ -3,28 +3,27 @@ import java.util.Optional; import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; -import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.internal.grpc.GrpcTransport; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; -public class WeaviateQueryClient +public class WeaviateQueryClient extends - AbstractQueryClient>, QueryResponse, QueryResponseGrouped> { + AbstractQueryClient>, QueryResponse, QueryResponseGrouped> { public WeaviateQueryClient( - CollectionDescriptor collection, + CollectionDescriptor collection, GrpcTransport grpcTransport, CollectionHandleDefaults defaults) { super(collection, grpcTransport, defaults); } /** Copy constructor that sets new defaults. */ - public WeaviateQueryClient(WeaviateQueryClient c, CollectionHandleDefaults defaults) { + public WeaviateQueryClient(WeaviateQueryClient c, CollectionHandleDefaults defaults) { super(c, defaults); } @Override - protected Optional> byId(ById byId) { + protected Optional> byId(ById byId) { var request = new QueryRequest(byId, null); var result = this.grpcTransport.performRequest(request, QueryRequest.rpc(collection, defaults)); return optionalFirst(result); @@ -32,13 +31,13 @@ protected Optional> byId(ById byId) { } @Override - protected final QueryResponse performRequest(QueryOperator operator) { + protected final QueryResponse performRequest(QueryOperator operator) { var request = new QueryRequest(operator, null); return this.grpcTransport.performRequest(request, QueryRequest.rpc(collection, defaults)); } @Override - protected final QueryResponseGrouped performRequest(QueryOperator operator, GroupBy groupBy) { + protected final QueryResponseGrouped performRequest(QueryOperator operator, GroupBy groupBy) { var request = new QueryRequest(operator, groupBy); return this.grpcTransport.performRequest(request, QueryRequest.grouped(collection, defaults)); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientAsync.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientAsync.java index a774d0e29..1f8276148 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientAsync.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientAsync.java @@ -4,28 +4,27 @@ import java.util.concurrent.CompletableFuture; import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; -import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.internal.grpc.GrpcTransport; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; -public class WeaviateQueryClientAsync +public class WeaviateQueryClientAsync extends - AbstractQueryClient>>, CompletableFuture>, CompletableFuture>> { + AbstractQueryClient>>, CompletableFuture>, CompletableFuture>> { public WeaviateQueryClientAsync( - CollectionDescriptor collection, + CollectionDescriptor collection, GrpcTransport grpcTransport, CollectionHandleDefaults defaults) { super(collection, grpcTransport, defaults); } /** Copy constructor that sets new defaults. */ - public WeaviateQueryClientAsync(WeaviateQueryClientAsync qc, CollectionHandleDefaults defaults) { + public WeaviateQueryClientAsync(WeaviateQueryClientAsync qc, CollectionHandleDefaults defaults) { super(qc, defaults); } @Override - protected CompletableFuture>> byId( + protected CompletableFuture>> byId( ById byId) { var request = new QueryRequest(byId, null); var result = this.grpcTransport.performRequestAsync(request, QueryRequest.rpc(collection, defaults)); @@ -33,13 +32,14 @@ protected CompletableFuture>> } @Override - protected final CompletableFuture> performRequest(QueryOperator operator) { + protected final CompletableFuture> performRequest(QueryOperator operator) { var request = new QueryRequest(operator, null); return this.grpcTransport.performRequestAsync(request, QueryRequest.rpc(collection, defaults)); } @Override - protected final CompletableFuture> performRequest(QueryOperator operator, GroupBy groupBy) { + protected final CompletableFuture> performRequest(QueryOperator operator, + GroupBy groupBy) { var request = new QueryRequest(operator, groupBy); return this.grpcTransport.performRequestAsync(request, QueryRequest.grouped(collection, defaults)); } diff --git a/src/main/java/io/weaviate/client6/v1/internal/json/JSON.java b/src/main/java/io/weaviate/client6/v1/internal/json/JSON.java index 344409495..11be4732b 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/json/JSON.java +++ b/src/main/java/io/weaviate/client6/v1/internal/json/JSON.java @@ -20,8 +20,6 @@ public final class JSON { io.weaviate.client6.v1.api.rbac.Permission.CustomTypeAdapterFactory.INSTANCE); gsonBuilder.registerTypeAdapterFactory( io.weaviate.client6.v1.api.rbac.Role.CustomTypeAdapterFactory.INSTANCE); - gsonBuilder.registerTypeAdapterFactory( - io.weaviate.client6.v1.api.collections.WeaviateObject.CustomTypeAdapterFactory.INSTANCE); gsonBuilder.registerTypeAdapterFactory( io.weaviate.client6.v1.api.collections.data.WriteWeaviateObject.CustomTypeAdapterFactory.INSTANCE); gsonBuilder.registerTypeAdapterFactory( diff --git a/src/test/java/io/weaviate/client6/v1/internal/json/JSONTest.java b/src/test/java/io/weaviate/client6/v1/internal/json/JSONTest.java index 8e3353227..dfa836076 100644 --- a/src/test/java/io/weaviate/client6/v1/internal/json/JSONTest.java +++ b/src/test/java/io/weaviate/client6/v1/internal/json/JSONTest.java @@ -18,7 +18,6 @@ import io.weaviate.client6.v1.api.collections.CollectionConfig; import io.weaviate.client6.v1.api.collections.Encoding; import io.weaviate.client6.v1.api.collections.Generative; -import io.weaviate.client6.v1.api.collections.ObjectMetadata; import io.weaviate.client6.v1.api.collections.Property; import io.weaviate.client6.v1.api.collections.Quantization; import io.weaviate.client6.v1.api.collections.ReferenceProperty; @@ -26,10 +25,10 @@ import io.weaviate.client6.v1.api.collections.Tokenization; import io.weaviate.client6.v1.api.collections.VectorConfig; import io.weaviate.client6.v1.api.collections.Vectors; -import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.api.collections.data.BatchReference; import io.weaviate.client6.v1.api.collections.data.Reference; import io.weaviate.client6.v1.api.collections.data.ReferenceAddManyResponse; +import io.weaviate.client6.v1.api.collections.data.WriteWeaviateObject; import io.weaviate.client6.v1.api.collections.quantizers.PQ; import io.weaviate.client6.v1.api.collections.rerankers.CohereReranker; import io.weaviate.client6.v1.api.collections.vectorindex.Distance; @@ -414,15 +413,20 @@ public static Object[][] testCases() { "{\"beacon\": \"weaviate://localhost/Doodlebops/id-1\"}", }, - // WeaviateObject.CustomTypeAdapterFactory.INSTANCE + // WriteWeaviateObject.CustomTypeAdapterFactory.INSTANCE { - new TypeToken, Reference, ObjectMetadata>>() { + new TypeToken>>() { }, - new WeaviateObject<>( + new WriteWeaviateObject<>( + "thing-1", "Things", + /* tenant */ null, Map.of("title", "ThingOne"), - Map.of("hasRef", List.of(Reference.uuids("ref-1"))), - ObjectMetadata.of(meta -> meta.uuid("thing-1"))), + /* vectors */ null, + /* creationTimeUnix */ null, + /* lastUpdateTimeUnix */ null, + Map.of("hasRef", List.of(Reference.uuids("ref-1")))), + """ { "class": "Things", From aa5ebece898cd7d10b37b9a65deda8d2d0449116 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Wed, 19 Nov 2025 15:43:25 +0100 Subject: [PATCH 03/11] chore: rename IWeaviateObject -> WeaviateObject --- .../{IWeaviateObject.java => WeaviateObject.java} | 4 +++- .../v1/api/collections/data/BatchReference.java | 8 ++++---- .../client6/v1/api/collections/data/Reference.java | 10 +++++----- .../v1/api/collections/data/WriteWeaviateObject.java | 4 ++-- .../v1/api/collections/query/QueryWeaviateObject.java | 4 ++-- 5 files changed, 16 insertions(+), 14 deletions(-) rename src/main/java/io/weaviate/client6/v1/api/collections/{IWeaviateObject.java => WeaviateObject.java} (53%) diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/IWeaviateObject.java b/src/main/java/io/weaviate/client6/v1/api/collections/WeaviateObject.java similarity index 53% rename from src/main/java/io/weaviate/client6/v1/api/collections/IWeaviateObject.java rename to src/main/java/io/weaviate/client6/v1/api/collections/WeaviateObject.java index 8e52285be..6e2d76f92 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/IWeaviateObject.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/WeaviateObject.java @@ -1,5 +1,7 @@ package io.weaviate.client6.v1.api.collections; -public interface IWeaviateObject { +public interface WeaviateObject { String uuid(); + + String collection(); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/BatchReference.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/BatchReference.java index c75220a26..9854a57bc 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/BatchReference.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/BatchReference.java @@ -7,12 +7,12 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; -import io.weaviate.client6.v1.api.collections.IWeaviateObject; +import io.weaviate.client6.v1.api.collections.WeaviateObject; public record BatchReference(String fromCollection, String fromProperty, String fromUuid, Reference reference) { - public static BatchReference[] objects(IWeaviateObject fromObject, String fromProperty, - IWeaviateObject... toObjects) { + public static BatchReference[] objects(WeaviateObject fromObject, String fromProperty, + WeaviateObject... toObjects) { return Arrays.stream(toObjects) .map(to -> new BatchReference( fromObject.collection(), fromProperty, fromObject.uuid(), @@ -20,7 +20,7 @@ public static BatchReference[] objects(IWeaviateObject fromObject, String fromPr .toArray(BatchReference[]::new); } - public static BatchReference[] uuids(IWeaviateObject fromObject, String fromProperty, + public static BatchReference[] uuids(WeaviateObject fromObject, String fromProperty, String... toUuids) { return Arrays.stream(toUuids) .map(to -> new BatchReference( diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/Reference.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/Reference.java index 302b90866..1b850094d 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/Reference.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/Reference.java @@ -8,7 +8,7 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; -import io.weaviate.client6.v1.api.collections.IWeaviateObject; +import io.weaviate.client6.v1.api.collections.WeaviateObject; public record Reference(String collection, List uuids) { @@ -27,13 +27,13 @@ public static Reference uuids(String... uuids) { return new Reference(null, Arrays.asList(uuids)); } - /** Create references to single {@link IWeaviateObject}. */ - public static Reference object(IWeaviateObject object) { + /** Create references to single {@link WeaviateObject}. */ + public static Reference object(WeaviateObject object) { return new Reference(object.collection(), object.uuid()); } - /** Create references to multiple {@link IWeaviateObject}. */ - public static Reference[] objects(IWeaviateObject... objects) { + /** Create references to multiple {@link WeaviateObject}. */ + public static Reference[] objects(WeaviateObject... objects) { return Arrays.stream(objects) .map(o -> new Reference(o.collection(), o.uuid())) .toArray(Reference[]::new); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/WriteWeaviateObject.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/WriteWeaviateObject.java index af4d0cb68..3d20c35c7 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/WriteWeaviateObject.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/WriteWeaviateObject.java @@ -19,7 +19,7 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; -import io.weaviate.client6.v1.api.collections.IWeaviateObject; +import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.api.collections.Vectors; import io.weaviate.client6.v1.internal.ObjectBuilder; @@ -32,7 +32,7 @@ public record WriteWeaviateObject( @SerializedName("creationTimeUnix") Long createdAt, @SerializedName("lastUpdateTimeUnix") Long lastUpdatedAt, - Map> references) implements IWeaviateObject { + Map> references) implements WeaviateObject { public static WriteWeaviateObject of( Function, ObjectBuilder>> fn) { diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryWeaviateObject.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryWeaviateObject.java index 1f0ad5f58..e1a7d6c07 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryWeaviateObject.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryWeaviateObject.java @@ -3,14 +3,14 @@ import java.util.List; import java.util.Map; -import io.weaviate.client6.v1.api.collections.IWeaviateObject; +import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.api.collections.Vectors; public record QueryWeaviateObject( String collection, PropertiesT properties, Map>> references, - QueryMetadata metadata) implements IWeaviateObject { + QueryMetadata metadata) implements WeaviateObject { /** Shorthand for accesing objects's UUID from metadata. */ @Override From b7c2020213860fd9168a25973620b3b53d5d4888 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Wed, 19 Nov 2025 17:06:24 +0100 Subject: [PATCH 04/11] fix: adjust as per failing tests --- .../collections/data/InsertManyRequest.java | 34 +++++++++++-------- .../collections/data/InsertObjectRequest.java | 2 +- .../v1/api/collections/data/Reference.java | 7 ++++ .../collections/data/ReferenceAddRequest.java | 1 - .../collections/data/WriteWeaviateObject.java | 31 +++++++++++------ 5 files changed, 47 insertions(+), 28 deletions(-) diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/InsertManyRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/InsertManyRequest.java index 161e4489d..843bdbb02 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/InsertManyRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/InsertManyRequest.java @@ -97,7 +97,9 @@ public static void buildObject(WeaviateProtoBatch.BatchObject.Builder object CollectionHandleDefaults defaults) { object.setCollection(collection.collectionName()); - object.setUuid(insert.uuid()); + if (insert.uuid() != null) { + object.setUuid(insert.uuid()); + } if (insert.vectors() != null) { var vectors = insert.vectors().asMap() @@ -125,21 +127,23 @@ public static void buildObject(WeaviateProtoBatch.BatchObject.Builder object var singleRef = new ArrayList(); var multiRef = new ArrayList(); - insert.references().entrySet().stream().forEach(entry -> { - var references = entry.getValue(); - - // dyma: How are we supposed to know if the reference - // is single- or multi-target? - for (var ref : references) { - if (ref.collection() == null) { - singleRef.add(WeaviateProtoBatch.BatchObject.SingleTargetRefProps.newBuilder().addAllUuids(ref.uuids()) - .setPropName(entry.getKey()).build()); - } else { - multiRef.add(WeaviateProtoBatch.BatchObject.MultiTargetRefProps.newBuilder() - .setTargetCollection(ref.collection()).addAllUuids(ref.uuids()).setPropName(entry.getKey()).build()); + if (insert.references() != null) { + insert.references().entrySet().stream().forEach(entry -> { + var references = entry.getValue(); + + // dyma: How are we supposed to know if the reference + // is single- or multi-target? + for (var ref : references) { + if (ref.collection() == null) { + singleRef.add(WeaviateProtoBatch.BatchObject.SingleTargetRefProps.newBuilder().addAllUuids(ref.uuids()) + .setPropName(entry.getKey()).build()); + } else { + multiRef.add(WeaviateProtoBatch.BatchObject.MultiTargetRefProps.newBuilder() + .setTargetCollection(ref.collection()).addAllUuids(ref.uuids()).setPropName(entry.getKey()).build()); + } } - } - }); + }); + } var properties = WeaviateProtoBatch.BatchObject.Properties.newBuilder() .addAllSingleTargetRefProps(singleRef) diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/InsertObjectRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/InsertObjectRequest.java index 05ab58172..cf992eba7 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/InsertObjectRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/InsertObjectRequest.java @@ -32,7 +32,7 @@ public static final Endpoint, Wri request -> JSON.serialize( new WriteWeaviateObject<>( request.object.uuid(), - request.object.collection(), + collection.collectionName(), defaults.tenant(), request.object.properties(), request.object.vectors(), diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/Reference.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/Reference.java index 1b850094d..097478788 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/Reference.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/Reference.java @@ -6,6 +6,7 @@ import com.google.gson.TypeAdapter; import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; import io.weaviate.client6.v1.api.collections.WeaviateObject; @@ -80,6 +81,12 @@ public Reference read(JsonReader in) throws IOException { in.beginObject(); in.nextName(); // expect "beacon"? var beacon = in.nextString(); + + // Skip to the end of the object. There's going to be the "href" + // key too, which is irrelevant for us. + while (in.peek() != JsonToken.END_OBJECT) { + in.skipValue(); + } in.endObject(); beacon = beacon.replaceFirst("weaviate://localhost/", ""); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceAddRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceAddRequest.java index 21321327f..00a04c654 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceAddRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceAddRequest.java @@ -17,6 +17,5 @@ public static final Endpoint endpoint( + request.fromProperty, request -> defaults.queryParameters(), request -> JSON.serialize(request.reference)); - } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/WriteWeaviateObject.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/WriteWeaviateObject.java index 3d20c35c7..673157532 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/WriteWeaviateObject.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/WriteWeaviateObject.java @@ -3,8 +3,10 @@ import java.io.IOException; import java.lang.reflect.ParameterizedType; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import java.util.function.Function; import com.google.gson.Gson; @@ -19,8 +21,8 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; -import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.api.collections.Vectors; +import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.internal.ObjectBuilder; public record WriteWeaviateObject( @@ -52,12 +54,18 @@ public WriteWeaviateObject(Builder builder) { } public static class Builder implements ObjectBuilder> { - private String uuid; + /** + * The server should be providing default UUIDs, but it does not do that + * during batch inserts and we have to provide our own. + * Rather than make this behaviour special to {@code insertMany}, we are going + * to provide a fallback UUID "globally". + */ + private String uuid = UUID.randomUUID().toString(); private String collection; private String tenant; private PropertiesT properties; private Vectors vectors; - private Map> references; + private Map> references = new HashMap<>(); public Builder uuid(String uuid) { this.uuid = uuid; @@ -122,16 +130,16 @@ public TypeAdapter create(Gson gson, TypeToken typeToken) { var rawType = typeToken.getRawType(); if (rawType != WriteWeaviateObject.class || !(type instanceof ParameterizedType parameterized) - || parameterized.getActualTypeArguments().length < 1) { + || parameterized.getActualTypeArguments().length != 1) { return null; } var typeParams = parameterized.getActualTypeArguments(); final var propertiesType = typeParams[0]; - final TypeAdapter> delegate = (TypeAdapter>) gson + final var delegate = (TypeAdapter>) gson .getDelegateAdapter(this, typeToken); - final var propertiesAdapter = gson.getAdapter(TypeToken.get(propertiesType)); + final var propertiesAdapter = (TypeAdapter) gson.getAdapter(TypeToken.get(propertiesType)); final var referencesAdapter = gson.getAdapter(Reference.class); return (TypeAdapter) new TypeAdapter>() { @@ -139,11 +147,11 @@ public TypeAdapter create(Gson gson, TypeToken typeToken) { @Override public void write(JsonWriter out, WriteWeaviateObject value) throws IOException { var json = delegate.toJsonTree(value).getAsJsonObject(); - var properties = ((TypeAdapter) propertiesAdapter) - .toJsonTree(value.properties()) - .getAsJsonObject(); + var properties = value.properties() != null + ? propertiesAdapter.toJsonTree(value.properties()).getAsJsonObject() + : new JsonObject(); - if (!value.references().isEmpty()) { + if (value.references() != null && !value.references().isEmpty()) { for (var refEntry : value.references().entrySet()) { var beacons = new JsonArray(); for (var reference : refEntry.getValue()) { @@ -154,7 +162,7 @@ public void write(JsonWriter out, WriteWeaviateObject value) throws IOExcepti } } - json.add("properties", json); + json.add("properties", properties); json.remove("references"); Streams.write(json, out); } @@ -185,6 +193,7 @@ public WriteWeaviateObject read(JsonReader in) throws IOException { } json.add("references", objectReferences); + json.add("properties", objectProperties); return delegate.fromJsonTree(json); } }.nullSafe(); From a33a87f44edeac374a1d7b224b4f3a89ae3909ef Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Wed, 19 Nov 2025 17:32:00 +0100 Subject: [PATCH 05/11] chore: rename QueryWeaviateObject -> ReadWeaviateObject --- .../io/weaviate/integration/DataITest.java | 40 +++++++++---------- .../io/weaviate/integration/ORMITest.java | 4 +- .../weaviate/integration/PaginationITest.java | 4 +- .../weaviate/integration/ReferencesITest.java | 16 ++++---- .../io/weaviate/integration/SearchITest.java | 32 +++++++-------- .../api/collections/pagination/AsyncPage.java | 18 ++++----- .../pagination/AsyncPaginator.java | 10 ++--- .../pagination/CursorSpliterator.java | 14 +++---- .../api/collections/pagination/Paginator.java | 10 ++--- .../query/AbstractQueryClient.java | 2 +- .../collections/query/QueryObjectGrouped.java | 2 +- .../api/collections/query/QueryResponse.java | 14 +++---- ...ateObject.java => ReadWeaviateObject.java} | 6 +-- .../query/WeaviateQueryClient.java | 4 +- .../query/WeaviateQueryClientAsync.java | 4 +- 15 files changed, 90 insertions(+), 90 deletions(-) rename src/main/java/io/weaviate/client6/v1/api/collections/query/{QueryWeaviateObject.java => ReadWeaviateObject.java} (84%) diff --git a/src/it/java/io/weaviate/integration/DataITest.java b/src/it/java/io/weaviate/integration/DataITest.java index 77aec8ad6..413d71dfa 100644 --- a/src/it/java/io/weaviate/integration/DataITest.java +++ b/src/it/java/io/weaviate/integration/DataITest.java @@ -27,7 +27,7 @@ import io.weaviate.client6.v1.api.collections.query.Metadata.MetadataField; import io.weaviate.client6.v1.api.collections.query.QueryMetadata; import io.weaviate.client6.v1.api.collections.query.QueryReference; -import io.weaviate.client6.v1.api.collections.query.QueryWeaviateObject; +import io.weaviate.client6.v1.api.collections.query.ReadWeaviateObject; import io.weaviate.client6.v1.api.collections.query.Where; import io.weaviate.containers.Container; @@ -103,7 +103,7 @@ public void testBlobData() throws IOException { cat -> cat.returnProperties("img")); Assertions.assertThat(got).get() - .extracting(QueryWeaviateObject::properties, InstanceOfAssertFactories.MAP) + .extracting(ReadWeaviateObject::properties, InstanceOfAssertFactories.MAP) .extractingByKey("img").isEqualTo(ragdollPng); } @@ -152,10 +152,10 @@ public void testReferences_AddReplaceDelete() throws IOException { Assertions.assertThat(johnWithFriends).get() .as("friends after ADD") - .extracting(QueryWeaviateObject::references).extracting("hasFriend") - .asInstanceOf(InstanceOfAssertFactories.list(QueryWeaviateObject.class)) + .extracting(ReadWeaviateObject::references).extracting("hasFriend") + .asInstanceOf(InstanceOfAssertFactories.list(ReadWeaviateObject.class)) .hasSize(1) - .first().extracting(QueryWeaviateObject::properties, InstanceOfAssertFactories.MAP) + .first().extracting(ReadWeaviateObject::properties, InstanceOfAssertFactories.MAP) .returns("albie", friend -> friend.get("name")); // Act: replace reference @@ -172,10 +172,10 @@ public void testReferences_AddReplaceDelete() throws IOException { Assertions.assertThat(johnWithFriends).get() .as("friends after REPLACE") - .extracting(QueryWeaviateObject::references).extracting("hasFriend") - .asInstanceOf(InstanceOfAssertFactories.list(QueryWeaviateObject.class)) + .extracting(ReadWeaviateObject::references).extracting("hasFriend") + .asInstanceOf(InstanceOfAssertFactories.list(ReadWeaviateObject.class)) .hasSize(1) - .first().extracting(QueryWeaviateObject::properties, InstanceOfAssertFactories.MAP) + .first().extracting(ReadWeaviateObject::properties, InstanceOfAssertFactories.MAP) .returns("barbara", friend -> friend.get("name")); // Act: delete reference @@ -191,8 +191,8 @@ public void testReferences_AddReplaceDelete() throws IOException { Assertions.assertThat(johnWithFriends).get() .as("friends after DELETE") - .extracting(QueryWeaviateObject::references).extracting("hasFriend") - .asInstanceOf(InstanceOfAssertFactories.list(QueryWeaviateObject.class)) + .extracting(ReadWeaviateObject::references).extracting("hasFriend") + .asInstanceOf(InstanceOfAssertFactories.list(ReadWeaviateObject.class)) .isEmpty(); } @@ -218,7 +218,7 @@ public void testReplace() throws IOException { Assertions.assertThat(replacedIvanhoe).get() .as("has ONLY year property") - .extracting(QueryWeaviateObject::properties, InstanceOfAssertFactories.MAP) + .extracting(ReadWeaviateObject::properties, InstanceOfAssertFactories.MAP) .doesNotContain(Map.entry("title", "ivanhoe")) .contains(Map.entry("year", 1819L)); } @@ -268,20 +268,20 @@ public void testUpdate() throws IOException { .satisfies(book -> { Assertions.assertThat(book) .as("has both year and title property") - .extracting(QueryWeaviateObject::properties, InstanceOfAssertFactories.MAP) + .extracting(ReadWeaviateObject::properties, InstanceOfAssertFactories.MAP) .contains(Map.entry("title", "ivanhoe"), Map.entry("year", 1819L)); Assertions.assertThat(book) .as("has reference to Authors") - .extracting(QueryWeaviateObject::references, InstanceOfAssertFactories.MAP) - .extractingByKey("writtenBy", InstanceOfAssertFactories.list(QueryWeaviateObject.class)) + .extracting(ReadWeaviateObject::references, InstanceOfAssertFactories.MAP) + .extractingByKey("writtenBy", InstanceOfAssertFactories.list(ReadWeaviateObject.class)) .first() - .extracting(QueryWeaviateObject::properties, InstanceOfAssertFactories.MAP) + .extracting(ReadWeaviateObject::properties, InstanceOfAssertFactories.MAP) .contains(Map.entry("name", "walter scott")); Assertions.assertThat(book) .as("has a vector") - .extracting(QueryWeaviateObject::metadata) + .extracting(ReadWeaviateObject::metadata) .extracting(QueryMetadata::vectors) .returns(vector, Vectors::getDefaultSingle); }); @@ -393,10 +393,10 @@ public void testReferenceAddMany() throws IOException { Assertions.assertThat(goodburgAirports).get() .as("Goodburg has 3 airports") - .extracting(QueryWeaviateObject::references) + .extracting(ReadWeaviateObject::references) .extracting(references -> references.get("hasAirports"), - InstanceOfAssertFactories.list(QueryWeaviateObject.class)) - .extracting(QueryWeaviateObject::uuid) + InstanceOfAssertFactories.list(ReadWeaviateObject.class)) + .extracting(ReadWeaviateObject::uuid) .contains(alpha, bravo, charlie); } @@ -474,7 +474,7 @@ public void testDataTypes() throws IOException { // Assert Assertions.assertThat(got).get() - .extracting(QueryWeaviateObject::properties) + .extracting(ReadWeaviateObject::properties) .asInstanceOf(InstanceOfAssertFactories.map(String.class, Object.class)) // Most of PhoneNumber fields are only present on read and are null on write. .usingRecursiveComparison() diff --git a/src/it/java/io/weaviate/integration/ORMITest.java b/src/it/java/io/weaviate/integration/ORMITest.java index 48663b7ea..cbefcbf4f 100644 --- a/src/it/java/io/weaviate/integration/ORMITest.java +++ b/src/it/java/io/weaviate/integration/ORMITest.java @@ -20,7 +20,7 @@ import io.weaviate.client6.v1.api.collections.annotations.Collection; import io.weaviate.client6.v1.api.collections.annotations.Property; import io.weaviate.client6.v1.api.collections.data.InsertManyResponse.InsertObject; -import io.weaviate.client6.v1.api.collections.query.QueryWeaviateObject; +import io.weaviate.client6.v1.api.collections.query.ReadWeaviateObject; import io.weaviate.client6.v1.api.collections.query.Where; import io.weaviate.containers.Container; @@ -358,7 +358,7 @@ public void test_partialScan() throws IOException { // Assert Assertions.assertThat(got).get() - .extracting(QueryWeaviateObject::properties) + .extracting(ReadWeaviateObject::properties) .returns("Dystopia", Song::title) .returns(null, Song::album) .returns(0, Song::year) diff --git a/src/it/java/io/weaviate/integration/PaginationITest.java b/src/it/java/io/weaviate/integration/PaginationITest.java index 269d681c0..b5e789e2b 100644 --- a/src/it/java/io/weaviate/integration/PaginationITest.java +++ b/src/it/java/io/weaviate/integration/PaginationITest.java @@ -21,7 +21,7 @@ import io.weaviate.client6.v1.api.collections.pagination.PaginationException; import io.weaviate.client6.v1.api.collections.query.Metadata; import io.weaviate.client6.v1.api.collections.query.QueryMetadata; -import io.weaviate.client6.v1.api.collections.query.QueryWeaviateObject; +import io.weaviate.client6.v1.api.collections.query.ReadWeaviateObject; import io.weaviate.containers.Container; public class PaginationITest extends ConcurrentTest { @@ -47,7 +47,7 @@ public void testIterateAll() throws IOException { // Act: stream var gotStream = allThings.stream() - .map(QueryWeaviateObject::metadata).map(QueryMetadata::uuid).toList(); + .map(ReadWeaviateObject::metadata).map(QueryMetadata::uuid).toList(); // Assert Assertions.assertThat(gotStream) diff --git a/src/it/java/io/weaviate/integration/ReferencesITest.java b/src/it/java/io/weaviate/integration/ReferencesITest.java index ed8061262..c8b51acc3 100644 --- a/src/it/java/io/weaviate/integration/ReferencesITest.java +++ b/src/it/java/io/weaviate/integration/ReferencesITest.java @@ -15,7 +15,7 @@ import io.weaviate.client6.v1.api.collections.ReferenceProperty; import io.weaviate.client6.v1.api.collections.data.Reference; import io.weaviate.client6.v1.api.collections.query.QueryReference; -import io.weaviate.client6.v1.api.collections.query.QueryWeaviateObject; +import io.weaviate.client6.v1.api.collections.query.ReadWeaviateObject; import io.weaviate.containers.Container; /** @@ -99,9 +99,9 @@ public void testReferences() throws IOException { .as("Artists: fetch by id including hasAwards references") // Cast references to Map> - .extracting(QueryWeaviateObject::references, InstanceOfAssertFactories.map(String.class, List.class)) + .extracting(ReadWeaviateObject::references, InstanceOfAssertFactories.map(String.class, List.class)) .as("hasAwards object reference").extractingByKey("hasAwards") - .asInstanceOf(InstanceOfAssertFactories.list(QueryWeaviateObject.class)) + .asInstanceOf(InstanceOfAssertFactories.list(ReadWeaviateObject.class)) .extracting(object -> object.uuid()) .containsOnly( @@ -166,19 +166,19 @@ public void testNestedReferences() throws IOException { .as("Artists: fetch by id including nested references") // Cast references to Map> - .extracting(QueryWeaviateObject::references, InstanceOfAssertFactories.map(String.class, List.class)) + .extracting(ReadWeaviateObject::references, InstanceOfAssertFactories.map(String.class, List.class)) .as("hasAwards object reference").extractingByKey("hasAwards") - .asInstanceOf(InstanceOfAssertFactories.list(QueryWeaviateObject.class)) + .asInstanceOf(InstanceOfAssertFactories.list(ReadWeaviateObject.class)) .hasSize(1).allSatisfy(award -> Assertions.assertThat(award) .returns(grammy_1.uuid(), grammy -> grammy.uuid()) // Cast references to Map> - .extracting(QueryWeaviateObject::references, InstanceOfAssertFactories.map(String.class, List.class)) + .extracting(ReadWeaviateObject::references, InstanceOfAssertFactories.map(String.class, List.class)) .as("presentedBy object reference").extractingByKey("presentedBy") - .asInstanceOf(InstanceOfAssertFactories.list(QueryWeaviateObject.class)) + .asInstanceOf(InstanceOfAssertFactories.list(ReadWeaviateObject.class)) - .hasSize(1).extracting(QueryWeaviateObject::properties) + .hasSize(1).extracting(ReadWeaviateObject::properties) .allSatisfy(properties -> Assertions.assertThat(properties) .asInstanceOf(InstanceOfAssertFactories.map(String.class, Object.class)) .containsEntry("ceo", "Harvy Mason"))); diff --git a/src/it/java/io/weaviate/integration/SearchITest.java b/src/it/java/io/weaviate/integration/SearchITest.java index 9dbfa7e5c..2dcffb0b4 100644 --- a/src/it/java/io/weaviate/integration/SearchITest.java +++ b/src/it/java/io/weaviate/integration/SearchITest.java @@ -33,7 +33,7 @@ import io.weaviate.client6.v1.api.collections.query.Metadata; import io.weaviate.client6.v1.api.collections.query.QueryMetadata; import io.weaviate.client6.v1.api.collections.query.QueryResponseGroup; -import io.weaviate.client6.v1.api.collections.query.QueryWeaviateObject; +import io.weaviate.client6.v1.api.collections.query.ReadWeaviateObject; import io.weaviate.client6.v1.api.collections.query.SortBy; import io.weaviate.client6.v1.api.collections.query.Target; import io.weaviate.client6.v1.api.collections.query.Where; @@ -166,7 +166,7 @@ public void testNearText() throws IOException { .returnProperties("title")); Assertions.assertThat(result.objects()).hasSize(2) - .extracting(QueryWeaviateObject::properties).allSatisfy( + .extracting(ReadWeaviateObject::properties).allSatisfy( properties -> Assertions.assertThat(properties) .allSatisfy((_k, v) -> Assertions.assertThat((String) v).contains("Jungle"))); } @@ -229,7 +229,7 @@ public void testNearImage() throws IOException { opt -> opt.returnProperties("breed")); Assertions.assertThat(got.objects()).hasSize(1).first() - .extracting(QueryWeaviateObject::properties, InstanceOfAssertFactories.MAP) + .extracting(ReadWeaviateObject::properties, InstanceOfAssertFactories.MAP) .extractingByKey("breed").isEqualTo("ragdoll"); } @@ -288,7 +288,7 @@ public void testFetchObjectsWithSort() throws Exception { Assertions.assertThat(asc.objects()) .as("value asc") .hasSize(3) - .extracting(QueryWeaviateObject::properties) + .extracting(ReadWeaviateObject::properties) .extracting(object -> object.get("value")) .containsExactly(1L, 2L, 3L); @@ -299,7 +299,7 @@ public void testFetchObjectsWithSort() throws Exception { Assertions.assertThat(desc.objects()) .as("value desc") .hasSize(3) - .extracting(QueryWeaviateObject::properties) + .extracting(ReadWeaviateObject::properties) .extracting(object -> object.get("value")) .containsExactly(3L, 2L, 1L); } @@ -325,7 +325,7 @@ public void testBm25() throws IOException, InterruptedException, ExecutionExcept Assertions.assertThat(dollarWorlds.objects()) .hasSize(1) - .extracting(QueryWeaviateObject::metadata).extracting(QueryMetadata::uuid) + .extracting(ReadWeaviateObject::metadata).extracting(QueryMetadata::uuid) .containsOnly(want.uuid()); } @@ -357,7 +357,7 @@ public void testBm25_async() throws Exception, InterruptedException, ExecutionEx Assertions.assertThat(dollarWorlds.objects()) .hasSize(1) - .extracting(QueryWeaviateObject::metadata).extracting(QueryMetadata::uuid) + .extracting(ReadWeaviateObject::metadata).extracting(QueryMetadata::uuid) .containsOnly(want.uuid()); } } @@ -387,7 +387,7 @@ public void testNearObject() throws IOException { // Assert Assertions.assertThat(terrestrial.objects()) .hasSize(1) - .extracting(QueryWeaviateObject::metadata).extracting(WeaviateMetadata::uuid) + .extracting(ReadWeaviateObject::metadata).extracting(WeaviateMetadata::uuid) .containsOnly(lion.uuid()); } @@ -414,7 +414,7 @@ public void testHybrid() throws IOException { // Assert Assertions.assertThat(winterSport.objects()) .hasSize(1) - .extracting(QueryWeaviateObject::metadata).extracting(WeaviateMetadata::uuid) + .extracting(ReadWeaviateObject::metadata).extracting(WeaviateMetadata::uuid) .containsOnly(skiing.uuid()); var first = winterSport.objects().get(0); @@ -484,7 +484,7 @@ public void test_includeVectors() throws IOException { // Assert Assertions.assertThat(got).get() - .extracting(QueryWeaviateObject::vectors) + .extracting(ReadWeaviateObject::vectors) .returns(true, v -> v.contains("v1")) .returns(true, v -> v.contains("v2")) .returns(false, v -> v.contains("v3")); @@ -513,7 +513,7 @@ public void testMetadataAll() throws IOException { // Assert var metadataHybrid = Assertions.assertThat(gotHybrid.objects()) .hasSize(1) - .extracting(QueryWeaviateObject::metadata) + .extracting(ReadWeaviateObject::metadata) .first().actual(); Assertions.assertThat(metadataHybrid.uuid()).as("uuid").isNotNull().isEqualTo(frisbee.uuid()); @@ -524,7 +524,7 @@ public void testMetadataAll() throws IOException { var metadataNearText = Assertions.assertThat(gotNearText.objects()) .hasSize(1) - .extracting(QueryWeaviateObject::metadata) + .extracting(ReadWeaviateObject::metadata) .first().actual(); Assertions.assertThat(metadataNearText.uuid()).as("uuid").isNotNull().isEqualTo(frisbee.uuid()); @@ -564,7 +564,7 @@ public void testNearVector_targetVectors() throws IOException { q -> q.limit(1)); Assertions.assertThat(got123.objects()) .as("search v1d") - .hasSize(1).extracting(QueryWeaviateObject::uuid) + .hasSize(1).extracting(ReadWeaviateObject::uuid) .containsExactly(thing123.uuid()); var got456 = things.query.nearVector( @@ -572,7 +572,7 @@ public void testNearVector_targetVectors() throws IOException { q -> q.limit(1)); Assertions.assertThat(got456.objects()) .as("search v2d") - .hasSize(1).extracting(QueryWeaviateObject::uuid) + .hasSize(1).extracting(ReadWeaviateObject::uuid) .containsExactly(thing456.uuids().get(0)); } @@ -606,9 +606,9 @@ public void testGenerative_bm25() throws IOException { .hasSize(2) .allSatisfy(obj -> { Assertions.assertThat(obj).as("uuid shorthand") - .returns(obj.uuid(), GenerativeObject::uuid); + .returns(obj.uuid(), GenerativeObject::uuid); Assertions.assertThat(obj).as("vectors shorthand") - .returns(obj.vectors(), GenerativeObject::vectors); + .returns(obj.vectors(), GenerativeObject::vectors); }) .extracting(GenerativeObject::generative) .allSatisfy(generated -> { diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPage.java b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPage.java index 807e6a608..0e7046fbe 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPage.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPage.java @@ -7,31 +7,31 @@ import java.util.concurrent.CompletableFuture; import java.util.function.BiFunction; -import io.weaviate.client6.v1.api.collections.query.QueryWeaviateObject; +import io.weaviate.client6.v1.api.collections.query.ReadWeaviateObject; -public final class AsyncPage implements Iterable> { +public final class AsyncPage implements Iterable> { private final int pageSize; - private final BiFunction>>> fetch; + private final BiFunction>>> fetch; private final String cursor; - private List> currentPage = new ArrayList<>(); + private List> currentPage = new ArrayList<>(); AsyncPage(String cursor, int pageSize, - BiFunction>>> fetch) { + BiFunction>>> fetch) { this.cursor = cursor; this.pageSize = pageSize; this.fetch = fetch; } AsyncPage(String cursor, int pageSize, - BiFunction>>> fetch, - List> currentPage) { + BiFunction>>> fetch, + List> currentPage) { this(cursor, pageSize, fetch); this.currentPage = Collections.unmodifiableList(currentPage); } - List> items() { + List> items() { return currentPage; } @@ -68,7 +68,7 @@ public CompletableFuture> fetchNextPage() { } @Override - public Iterator> iterator() { + public Iterator> iterator() { return currentPage.iterator(); } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPaginator.java b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPaginator.java index 1163965bb..c82c2df3e 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPaginator.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPaginator.java @@ -9,7 +9,7 @@ import io.weaviate.client6.v1.api.collections.query.Metadata; import io.weaviate.client6.v1.api.collections.query.QueryReference; import io.weaviate.client6.v1.api.collections.query.QueryResponse; -import io.weaviate.client6.v1.api.collections.query.QueryWeaviateObject; +import io.weaviate.client6.v1.api.collections.query.ReadWeaviateObject; import io.weaviate.client6.v1.api.collections.query.WeaviateQueryClientAsync; import io.weaviate.client6.v1.internal.ObjectBuilder; @@ -45,25 +45,25 @@ public AsyncPaginator(Builder builder) { this.resultSet = builder.prefetch ? rs.fetchNextPage() : CompletableFuture.completedFuture(rs); } - public CompletableFuture forEach(Consumer> action) { + public CompletableFuture forEach(Consumer> action) { return resultSet .thenCompose(rs -> rs.isEmpty() ? rs.fetchNextPage() : CompletableFuture.completedFuture(rs)) .thenCompose(processEachAndAdvance(action)); } - public CompletableFuture forPage(Consumer>> action) { + public CompletableFuture forPage(Consumer>> action) { return resultSet .thenCompose(rs -> rs.isEmpty() ? rs.fetchNextPage() : CompletableFuture.completedFuture(rs)) .thenCompose(processPageAndAdvance(action)); } private static Function, CompletableFuture> processEachAndAdvance( - Consumer> action) { + Consumer> action) { return processAndAdvanceFunc(rs -> rs.forEach(action)); } private static Function, CompletableFuture> processPageAndAdvance( - Consumer>> action) { + Consumer>> action) { return processAndAdvanceFunc(rs -> action.accept(rs.items())); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/CursorSpliterator.java b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/CursorSpliterator.java index ddc0b2574..eb45e0402 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/CursorSpliterator.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/CursorSpliterator.java @@ -7,26 +7,26 @@ import java.util.function.BiFunction; import java.util.function.Consumer; -import io.weaviate.client6.v1.api.collections.query.QueryWeaviateObject; +import io.weaviate.client6.v1.api.collections.query.ReadWeaviateObject; -public class CursorSpliterator implements Spliterator> { +public class CursorSpliterator implements Spliterator> { private final int pageSize; - private final BiFunction>> fetch; + private final BiFunction>> fetch; // Spliterators do not promise thread-safety, so there's no mechanism // to protect access to its internal state. private String cursor; - private Iterator> currentPage = Collections.emptyIterator(); + private Iterator> currentPage = Collections.emptyIterator(); public CursorSpliterator(String cursor, int pageSize, - BiFunction>> fetch) { + BiFunction>> fetch) { this.cursor = cursor; this.pageSize = pageSize; this.fetch = fetch; } @Override - public boolean tryAdvance(Consumer> action) { + public boolean tryAdvance(Consumer> action) { // Happy path: there are remaining objects in the current page. if (currentPage.hasNext()) { action.accept(currentPage.next()); @@ -53,7 +53,7 @@ public boolean tryAdvance(Consumer> act } @Override - public Spliterator> trySplit() { + public Spliterator> trySplit() { // Do not support splitting just now; return null; } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/Paginator.java b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/Paginator.java index 089256c24..c90fb3c46 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/Paginator.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/Paginator.java @@ -11,12 +11,12 @@ import io.weaviate.client6.v1.api.collections.query.FetchObjects; import io.weaviate.client6.v1.api.collections.query.Metadata; import io.weaviate.client6.v1.api.collections.query.QueryReference; -import io.weaviate.client6.v1.api.collections.query.QueryWeaviateObject; +import io.weaviate.client6.v1.api.collections.query.ReadWeaviateObject; import io.weaviate.client6.v1.api.collections.query.WeaviateQueryClient; import io.weaviate.client6.v1.api.collections.query.Where; import io.weaviate.client6.v1.internal.ObjectBuilder; -public class Paginator implements Iterable> { +public class Paginator implements Iterable> { static final int DEFAULT_PAGE_SIZE = 100; private final WeaviateQueryClient query; @@ -25,15 +25,15 @@ public class Paginator implements Iterable> iterator() { + public Iterator> iterator() { return Spliterators.iterator(spliterator()); } - public Stream> stream() { + public Stream> stream() { return StreamSupport.stream(spliterator(), false); } - public Spliterator> spliterator() { + public Spliterator> spliterator() { return new CursorSpliterator(cursor, pageSize, (after, limit) -> { var fn = ObjectBuilder.partial(queryOptions, q -> q.after(after).limit(limit)); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/AbstractQueryClient.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/AbstractQueryClient.java index 178972617..b90c6d748 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/AbstractQueryClient.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/AbstractQueryClient.java @@ -72,7 +72,7 @@ public SingleT fetchObjectById(String uuid, Function Optional> optionalFirst(QueryResponse

response) { + protected final

Optional> optionalFirst(QueryResponse

response) { return response == null || response.objects().isEmpty() ? Optional.empty() : Optional.ofNullable(response.objects().get(0)); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryObjectGrouped.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryObjectGrouped.java index 562d03780..fb6b711d8 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryObjectGrouped.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryObjectGrouped.java @@ -8,7 +8,7 @@ public record QueryObjectGrouped( /** Name of the group that the object belongs to. */ String belongsToGroup) { - QueryObjectGrouped(QueryWeaviateObject object, + QueryObjectGrouped(ReadWeaviateObject object, String belongsToGroup) { this(object.properties(), object.metadata(), belongsToGroup); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryResponse.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryResponse.java index 49643e0fa..f804acde6 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryResponse.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryResponse.java @@ -17,7 +17,7 @@ import io.weaviate.client6.v1.internal.orm.PropertiesBuilder; public record QueryResponse( - List> objects) { + List> objects) { static QueryResponse unmarshal(WeaviateProtoSearchGet.SearchReply reply, CollectionDescriptor collection) { @@ -30,7 +30,7 @@ static QueryResponse unmarshal(WeaviateProtoSearchGet return new QueryResponse<>(objects); } - public static QueryWeaviateObject unmarshalResultObject( + public static ReadWeaviateObject unmarshalResultObject( WeaviateProtoSearchGet.PropertiesResult propertiesResult, WeaviateProtoSearchGet.MetadataResult metadataResult, CollectionDescriptor collection) { @@ -57,11 +57,11 @@ public static QueryWeaviateObject unmarshalResultObje if (metadataResult.getExplainScorePresent()) { metadata.explainScore(metadataResult.getExplainScore()); } - return new QueryWeaviateObject<>(collection.collectionName(), object.properties(), object.references(), + return new ReadWeaviateObject<>(collection.collectionName(), object.properties(), object.references(), metadata.build()); } - static QueryWeaviateObject unmarshalWithReferences( + static ReadWeaviateObject unmarshalWithReferences( WeaviateProtoSearchGet.PropertiesResult propertiesResult, WeaviateProtoSearchGet.MetadataResult metadataResult, CollectionDescriptor descriptor) { @@ -76,14 +76,14 @@ static QueryWeaviateObject unmarshalWithReferences( // I.e. { "ref": A-1 } , { "ref": B-1 } => { "ref": [A-1, B-1] } var referenceProperties = propertiesResult.getRefPropsList() .stream().reduce( - new HashMap>>(), + new HashMap>>(), (map, ref) -> { var refObjects = ref.getPropertiesList().stream() .map(property -> { var reference = unmarshalWithReferences( property, property.getMetadata(), CollectionDescriptor.ofMap(property.getTargetCollection())); - return new QueryWeaviateObject<>( + return new ReadWeaviateObject<>( reference.collection(), (Object) reference.properties(), reference.references(), @@ -133,7 +133,7 @@ static QueryWeaviateObject unmarshalWithReferences( metadata = metadataBuilder.build(); } - return new QueryWeaviateObject<>( + return new ReadWeaviateObject<>( descriptor.collectionName(), properties.build(), referenceProperties, diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryWeaviateObject.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/ReadWeaviateObject.java similarity index 84% rename from src/main/java/io/weaviate/client6/v1/api/collections/query/QueryWeaviateObject.java rename to src/main/java/io/weaviate/client6/v1/api/collections/query/ReadWeaviateObject.java index e1a7d6c07..0adaee11a 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryWeaviateObject.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/ReadWeaviateObject.java @@ -3,13 +3,13 @@ import java.util.List; import java.util.Map; -import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.api.collections.Vectors; +import io.weaviate.client6.v1.api.collections.WeaviateObject; -public record QueryWeaviateObject( +public record ReadWeaviateObject( String collection, PropertiesT properties, - Map>> references, + Map>> references, QueryMetadata metadata) implements WeaviateObject { /** Shorthand for accesing objects's UUID from metadata. */ diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClient.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClient.java index 9b13e1bf3..24c53b753 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClient.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClient.java @@ -8,7 +8,7 @@ public class WeaviateQueryClient extends - AbstractQueryClient>, QueryResponse, QueryResponseGrouped> { + AbstractQueryClient>, QueryResponse, QueryResponseGrouped> { public WeaviateQueryClient( CollectionDescriptor collection, @@ -23,7 +23,7 @@ public WeaviateQueryClient(WeaviateQueryClient c, CollectionHandleD } @Override - protected Optional> fetchObjectById(FetchObjectById byId) { + protected Optional> fetchObjectById(FetchObjectById byId) { var request = new QueryRequest(byId, null); var result = this.grpcTransport.performRequest(request, QueryRequest.rpc(collection, defaults)); return optionalFirst(result); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientAsync.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientAsync.java index ad0cc5db6..13bf9ce6d 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientAsync.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientAsync.java @@ -9,7 +9,7 @@ public class WeaviateQueryClientAsync extends - AbstractQueryClient>>, CompletableFuture>, CompletableFuture>> { + AbstractQueryClient>>, CompletableFuture>, CompletableFuture>> { public WeaviateQueryClientAsync( CollectionDescriptor collection, @@ -24,7 +24,7 @@ public WeaviateQueryClientAsync(WeaviateQueryClientAsync qc, Collec } @Override - protected CompletableFuture>> fetchObjectById( + protected CompletableFuture>> fetchObjectById( FetchObjectById byId) { var request = new QueryRequest(byId, null); var result = this.grpcTransport.performRequestAsync(request, QueryRequest.rpc(collection, defaults)); From 17cade1ce676bcbbe563dc35014cdd188b367092 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Wed, 19 Nov 2025 17:55:46 +0100 Subject: [PATCH 06/11] chore: add .vectors to WeaviateObject interface --- .../io/weaviate/client6/v1/api/collections/WeaviateObject.java | 2 ++ .../client6/v1/api/collections/query/ReadWeaviateObject.java | 1 + 2 files changed, 3 insertions(+) diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/WeaviateObject.java b/src/main/java/io/weaviate/client6/v1/api/collections/WeaviateObject.java index 6e2d76f92..dedc38849 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/WeaviateObject.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/WeaviateObject.java @@ -4,4 +4,6 @@ public interface WeaviateObject { String uuid(); String collection(); + + Vectors vectors(); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/ReadWeaviateObject.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/ReadWeaviateObject.java index 0adaee11a..7f8505b79 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/ReadWeaviateObject.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/ReadWeaviateObject.java @@ -19,6 +19,7 @@ public String uuid() { } /** Shorthand for accesing objects's vectors from metadata. */ + @Override public Vectors vectors() { return metadata.vectors(); } From 5dfd10448125a9e92efcd0360d8487c3c4ab86dc Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Fri, 21 Nov 2025 10:59:22 +0100 Subject: [PATCH 07/11] test: add missing import --- src/it/java/io/weaviate/integration/SearchITest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/it/java/io/weaviate/integration/SearchITest.java b/src/it/java/io/weaviate/integration/SearchITest.java index c6c9f5c04..fa75389ea 100644 --- a/src/it/java/io/weaviate/integration/SearchITest.java +++ b/src/it/java/io/weaviate/integration/SearchITest.java @@ -21,11 +21,13 @@ import io.weaviate.ConcurrentTest; import io.weaviate.client6.v1.api.WeaviateApiException; import io.weaviate.client6.v1.api.WeaviateClient; +import io.weaviate.client6.v1.api.collections.ObjectMetadata; import io.weaviate.client6.v1.api.collections.Property; import io.weaviate.client6.v1.api.collections.ReferenceProperty; import io.weaviate.client6.v1.api.collections.VectorConfig; import io.weaviate.client6.v1.api.collections.Vectors; import io.weaviate.client6.v1.api.collections.WeaviateMetadata; +import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.api.collections.data.Reference; import io.weaviate.client6.v1.api.collections.data.WriteWeaviateObject; import io.weaviate.client6.v1.api.collections.generate.GenerativeObject; @@ -739,7 +741,7 @@ public void teset_filterPropertyLength() throws IOException { // Assertions Assertions.assertThat(got.objects()).hasSize(2); } - + /** * Ensure the client respects server's configuration for max gRPC size: * we create a server with 1-byte message size and try to send a large payload From ec7b22f3121204d2a12c0a3e8c41a6c72d4a47a5 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Fri, 21 Nov 2025 11:02:22 +0100 Subject: [PATCH 08/11] test: use new syntax for inserting objects --- src/it/java/io/weaviate/integration/SearchITest.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/it/java/io/weaviate/integration/SearchITest.java b/src/it/java/io/weaviate/integration/SearchITest.java index fa75389ea..010e05fb3 100644 --- a/src/it/java/io/weaviate/integration/SearchITest.java +++ b/src/it/java/io/weaviate/integration/SearchITest.java @@ -21,13 +21,11 @@ import io.weaviate.ConcurrentTest; import io.weaviate.client6.v1.api.WeaviateApiException; import io.weaviate.client6.v1.api.WeaviateClient; -import io.weaviate.client6.v1.api.collections.ObjectMetadata; import io.weaviate.client6.v1.api.collections.Property; import io.weaviate.client6.v1.api.collections.ReferenceProperty; import io.weaviate.client6.v1.api.collections.VectorConfig; import io.weaviate.client6.v1.api.collections.Vectors; import io.weaviate.client6.v1.api.collections.WeaviateMetadata; -import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.api.collections.data.Reference; import io.weaviate.client6.v1.api.collections.data.WriteWeaviateObject; import io.weaviate.client6.v1.api.collections.generate.GenerativeObject; @@ -758,9 +756,8 @@ public void test_maxGrpcMessageSize() throws Exception { .vectorConfig(VectorConfig.selfProvided())); final var vector = randomVector(5000, -.01f, .01f); - final WeaviateObject, Reference, ObjectMetadata> hugeObject = WeaviateObject.of(obj -> obj - .metadata(ObjectMetadata.of(m -> m - .vectors(Vectors.of(vector))))); + final WriteWeaviateObject> hugeObject = WriteWeaviateObject.of( + obj -> obj.vectors(Vectors.of(vector))); Assertions.assertThatThrownBy(() -> { // insertMany to route this request through gRPC. From cd5a1eb5b680851f1d2469907aa2ef5309e92dfc Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Fri, 21 Nov 2025 11:53:11 +0100 Subject: [PATCH 09/11] test: get tenant from inserted object --- .../io/weaviate/integration/DataITest.java | 23 ++++++++++++++++++- .../v1/api/collections/CollectionConfig.java | 11 ++++----- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/it/java/io/weaviate/integration/DataITest.java b/src/it/java/io/weaviate/integration/DataITest.java index d4b2f39d6..743606ada 100644 --- a/src/it/java/io/weaviate/integration/DataITest.java +++ b/src/it/java/io/weaviate/integration/DataITest.java @@ -23,12 +23,14 @@ import io.weaviate.client6.v1.api.collections.data.BatchReference; import io.weaviate.client6.v1.api.collections.data.DeleteManyResponse; import io.weaviate.client6.v1.api.collections.data.Reference; +import io.weaviate.client6.v1.api.collections.data.WriteWeaviateObject; +import io.weaviate.client6.v1.api.collections.query.Filter; import io.weaviate.client6.v1.api.collections.query.Metadata; import io.weaviate.client6.v1.api.collections.query.Metadata.MetadataField; import io.weaviate.client6.v1.api.collections.query.QueryMetadata; import io.weaviate.client6.v1.api.collections.query.QueryReference; import io.weaviate.client6.v1.api.collections.query.ReadWeaviateObject; -import io.weaviate.client6.v1.api.collections.query.Filter; +import io.weaviate.client6.v1.api.collections.tenants.Tenant; import io.weaviate.containers.Container; public class DataITest extends ConcurrentTest { @@ -86,6 +88,7 @@ public void testCreateGetDelete() throws IOException { .as("object not exists after deletion").isFalse(); deleted = artists.data.deleteById(id); + // TODO: Change to isFalse() after fixed in Weaviate server Assertions.assertThat(deleted) .as("object wasn't deleted").isTrue(); @@ -536,4 +539,22 @@ public void testNestedProperties_insertMany() throws IOException { // Assert Assertions.assertThat(result.errors()).isEmpty(); } + + @Test + public void test_multiTenant() throws IOException { + // Arrange + var nsEmails = ns("Emails"); + var emails = client.collections.create(nsEmails, + c -> c.multiTenancy(mt -> mt.enabled(true))); + + var johndoe = "john-doe"; + emails.tenants.create(Tenant.active(johndoe)); + emails = emails.withTenant(johndoe); + + // Act + var inserted = emails.data.insert(Map.of("subject", "McDonald's Xmas Bonanza")); + + // Assert + Assertions.assertThat(inserted).returns(johndoe, WriteWeaviateObject::tenant); + } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionConfig.java b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionConfig.java index 634bd9713..9befaffc7 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionConfig.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionConfig.java @@ -33,7 +33,7 @@ public record CollectionConfig( List references, /** Vector indexes configured for this collection. */ @SerializedName("vectorConfig") Map vectors, - /** Multi-tenantcy options. */ + /** Multi-tenancy options. */ @SerializedName("multiTenancyConfig") MultiTenancy multiTenancy, /** Sharding configuration. */ @SerializedName("shardingConfig") Sharding sharding, @@ -193,14 +193,13 @@ public Builder sharding(Function> fn) } /** Configure multi-tenancy. */ - public Builder multiTenancy(MultiTenancy multiTenancy) { - this.multiTenancy = multiTenancy; - return this; + public Builder multiTenancy(Function> fn) { + return multiTenancy(MultiTenancy.of(fn)); } /** Configure multi-tenancy. */ - public Builder multiTenancy(Function> fn) { - this.multiTenancy = MultiTenancy.of(fn); + public Builder multiTenancy(MultiTenancy multiTenancy) { + this.multiTenancy = multiTenancy; return this; } From 67ee9a33b9e17e6d717a183bcac0d30e256276a4 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Fri, 21 Nov 2025 15:42:03 +0100 Subject: [PATCH 10/11] test: disable tests that's causing side-effects This is _definitely_ a server-side issue and needs investigating --- src/it/java/io/weaviate/integration/DataITest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/it/java/io/weaviate/integration/DataITest.java b/src/it/java/io/weaviate/integration/DataITest.java index 743606ada..349ce5253 100644 --- a/src/it/java/io/weaviate/integration/DataITest.java +++ b/src/it/java/io/weaviate/integration/DataITest.java @@ -9,6 +9,7 @@ import org.assertj.core.api.Assertions; import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; import io.weaviate.ConcurrentTest; @@ -540,6 +541,7 @@ public void testNestedProperties_insertMany() throws IOException { Assertions.assertThat(result.errors()).isEmpty(); } + @Ignore("Making Emails collection multi-tenant causes ReferencesITest::testNestedReferences to fail") @Test public void test_multiTenant() throws IOException { // Arrange From 3aef0cf81bad681a0fe6eedec4d38ab3423777c0 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Fri, 21 Nov 2025 15:42:43 +0100 Subject: [PATCH 11/11] chore: fix malformed import --- src/it/java/io/weaviate/integration/SearchITest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/it/java/io/weaviate/integration/SearchITest.java b/src/it/java/io/weaviate/integration/SearchITest.java index 250409095..d37a6718c 100644 --- a/src/it/java/io/weaviate/integration/SearchITest.java +++ b/src/it/java/io/weaviate/integration/SearchITest.java @@ -21,6 +21,7 @@ import io.weaviate.ConcurrentTest; import io.weaviate.client6.v1.api.WeaviateApiException; import io.weaviate.client6.v1.api.WeaviateClient; +import io.weaviate.client6.v1.api.collections.Generative; import io.weaviate.client6.v1.api.collections.Property; import io.weaviate.client6.v1.api.collections.ReferenceProperty; import io.weaviate.client6.v1.api.collections.Reranker; @@ -29,7 +30,7 @@ import io.weaviate.client6.v1.api.collections.WeaviateMetadata; import io.weaviate.client6.v1.api.collections.data.Reference; import io.weaviate.client6.v1.api.collections.data.WriteWeaviateObject; -import io.weaviate.client6.v1.api.collections.generate. +import io.weaviate.client6.v1.api.collections.generate.GenerativeObject; import io.weaviate.client6.v1.api.collections.generate.TaskOutput; import io.weaviate.client6.v1.api.collections.generative.DummyGenerative; import io.weaviate.client6.v1.api.collections.query.Filter;