From 80a8936c55ae333628e392a9a012313f50938328 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 18 Aug 2025 12:34:31 +0200 Subject: [PATCH 01/24] feat: apply default consistencyLevel to queries --- .../v1/api/collections/CollectionHandle.java | 42 +++++++--- .../collections/CollectionHandleAsync.java | 31 +++++++- .../collections/CollectionHandleDefaults.java | 45 +++++++++++ .../WeaviateCollectionsClient.java | 19 ++++- .../WeaviateCollectionsClientAsync.java | 13 +++- .../collections/data/WeaviateDataClient.java | 40 ++++++---- .../data/WeaviateDataClientAsync.java | 41 ++++++---- .../query/AbstractQueryClient.java | 78 +++++++++++++------ .../query/WeaviateQueryClient.java | 13 +++- .../query/WeaviateQueryClientAsync.java | 13 +++- .../CollectionHandleDefaultsTest.java | 52 +++++++++++++ 11 files changed, 315 insertions(+), 72 deletions(-) create mode 100644 src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java create mode 100644 src/test/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaultsTest.java diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandle.java b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandle.java index fb262cbc2..4233da870 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandle.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandle.java @@ -7,34 +7,50 @@ import io.weaviate.client6.v1.api.collections.config.WeaviateConfigClient; import io.weaviate.client6.v1.api.collections.data.WeaviateDataClient; import io.weaviate.client6.v1.api.collections.pagination.Paginator; +import io.weaviate.client6.v1.api.collections.query.ConsistencyLevel; import io.weaviate.client6.v1.api.collections.query.WeaviateQueryClient; import io.weaviate.client6.v1.internal.ObjectBuilder; import io.weaviate.client6.v1.internal.grpc.GrpcTransport; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; import io.weaviate.client6.v1.internal.rest.RestTransport; -public class CollectionHandle { +public class CollectionHandle { public final WeaviateConfigClient config; - public final WeaviateDataClient data; - public final WeaviateQueryClient query; + public final WeaviateDataClient data; + public final WeaviateQueryClient query; public final WeaviateAggregateClient aggregate; + private final CollectionHandleDefaults defaults; + public CollectionHandle( RestTransport restTransport, GrpcTransport grpcTransport, - CollectionDescriptor collectionDescriptor) { - + CollectionDescriptor collectionDescriptor, + CollectionHandleDefaults defaults) { this.config = new WeaviateConfigClient(collectionDescriptor, restTransport, grpcTransport); - this.data = new WeaviateDataClient<>(collectionDescriptor, restTransport, grpcTransport); - this.query = new WeaviateQueryClient<>(collectionDescriptor, grpcTransport); this.aggregate = new WeaviateAggregateClient(collectionDescriptor, grpcTransport); + this.query = new WeaviateQueryClient<>(collectionDescriptor, grpcTransport, defaults); + this.data = new WeaviateDataClient<>(collectionDescriptor, restTransport, grpcTransport, query); + + this.defaults = defaults; + } + + /** Copy constructor that sets new defaults. */ + private CollectionHandle(CollectionHandle c, CollectionHandleDefaults defaults) { + this.config = c.config; + this.aggregate = c.aggregate; + this.query = new WeaviateQueryClient<>(c.query, defaults); + this.data = new WeaviateDataClient<>(c.data, query); + + this.defaults = defaults; } - public Paginator paginate() { + public Paginator paginate() { return Paginator.of(this.query); } - public Paginator paginate(Function, ObjectBuilder>> fn) { + public Paginator paginate( + Function, ObjectBuilder>> fn) { return Paginator.of(this.query, fn); } @@ -57,4 +73,12 @@ public Paginator paginate(Function, ObjectBuilder all.includeTotalCount(true)).totalCount(); } + + public ConsistencyLevel consistencyLevel() { + return defaults.consistencyLevel(); + } + + public CollectionHandle withConsistencyLevel(ConsistencyLevel consistencyLevel) { + return new CollectionHandle<>(this, CollectionHandleDefaults.of(def -> def.consistencyLevel(consistencyLevel))); + } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleAsync.java b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleAsync.java index 9a646d518..997067799 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleAsync.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleAsync.java @@ -9,6 +9,7 @@ import io.weaviate.client6.v1.api.collections.config.WeaviateConfigClientAsync; import io.weaviate.client6.v1.api.collections.data.WeaviateDataClientAsync; import io.weaviate.client6.v1.api.collections.pagination.AsyncPaginator; +import io.weaviate.client6.v1.api.collections.query.ConsistencyLevel; import io.weaviate.client6.v1.api.collections.query.WeaviateQueryClientAsync; import io.weaviate.client6.v1.internal.ObjectBuilder; import io.weaviate.client6.v1.internal.grpc.GrpcTransport; @@ -21,15 +22,30 @@ public class CollectionHandleAsync { public final WeaviateQueryClientAsync query; public final WeaviateAggregateClientAsync aggregate; + private final CollectionHandleDefaults defaults; + public CollectionHandleAsync( RestTransport restTransport, GrpcTransport grpcTransport, - CollectionDescriptor collectionDescriptor) { + CollectionDescriptor collectionDescriptor, + CollectionHandleDefaults defaults) { this.config = new WeaviateConfigClientAsync(collectionDescriptor, restTransport, grpcTransport); - this.data = new WeaviateDataClientAsync<>(collectionDescriptor, restTransport, grpcTransport); - this.query = new WeaviateQueryClientAsync<>(collectionDescriptor, grpcTransport); this.aggregate = new WeaviateAggregateClientAsync(collectionDescriptor, grpcTransport); + this.query = new WeaviateQueryClientAsync<>(collectionDescriptor, grpcTransport, defaults); + this.data = new WeaviateDataClientAsync<>(collectionDescriptor, restTransport, grpcTransport, query); + + this.defaults = defaults; + } + + /** Copy constructor that sets new defaults. */ + private CollectionHandleAsync(CollectionHandleAsync c, CollectionHandleDefaults defaults) { + this.config = c.config; + this.aggregate = c.aggregate; + this.query = new WeaviateQueryClientAsync<>(c.query, defaults); + this.data = new WeaviateDataClientAsync<>(c.data, query); + + this.defaults = defaults; } public AsyncPaginator paginate() { @@ -64,4 +80,13 @@ public CompletableFuture size() { return this.aggregate.overAll(all -> all.includeTotalCount(true)) .thenApply(AggregateResponse::totalCount); } + + public ConsistencyLevel consistencyLevel() { + return defaults.consistencyLevel(); + } + + public CollectionHandleAsync withConsistencyLevel(ConsistencyLevel consistencyLevel) { + return new CollectionHandleAsync<>(this, CollectionHandleDefaults.of( + def -> def.consistencyLevel(consistencyLevel))); + } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java new file mode 100644 index 000000000..b1b549d1e --- /dev/null +++ b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java @@ -0,0 +1,45 @@ +package io.weaviate.client6.v1.api.collections; + +import java.util.function.Function; + +import io.weaviate.client6.v1.api.collections.query.ConsistencyLevel; +import io.weaviate.client6.v1.internal.ObjectBuilder; + +public record CollectionHandleDefaults(ConsistencyLevel consistencyLevel) { + /** + * Set default values for query / aggregation requests. + * + * @return CollectionHandleDefaults derived from applying {@code fn} to + * {@link Builder}. + */ + public static CollectionHandleDefaults of(Function> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * Empty collection defaults. + * + * @return An tucked builder that does not leaves all defaults unset. + */ + public static Function> none() { + return ObjectBuilder.identity(); + } + + public CollectionHandleDefaults(Builder builder) { + this(builder.consistencyLevel); + } + + public static final class Builder implements ObjectBuilder { + private ConsistencyLevel consistencyLevel; + + public Builder consistencyLevel(ConsistencyLevel consistencyLevel) { + this.consistencyLevel = consistencyLevel; + return this; + } + + @Override + public CollectionHandleDefaults build() { + return new CollectionHandleDefaults(this); + } + } +} diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/WeaviateCollectionsClient.java b/src/main/java/io/weaviate/client6/v1/api/collections/WeaviateCollectionsClient.java index d8c175692..f71d7e9e9 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/WeaviateCollectionsClient.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/WeaviateCollectionsClient.java @@ -29,7 +29,24 @@ public WeaviateCollectionsClient(RestTransport restTransport, GrpcTransport grpc * properties. */ public CollectionHandle> use(String collectionName) { - return new CollectionHandle<>(restTransport, grpcTransport, CollectionDescriptor.ofMap(collectionName)); + return use(collectionName, CollectionHandleDefaults.none()); + } + + /** + * Obtain a handle to send requests to a particular collection. + * The returned object is thread-safe. + * + * @return a handle for a collection with {@code Map} + * properties. + */ + public CollectionHandle> use( + String collectionName, + Function> fn) { + return new CollectionHandle<>( + restTransport, + grpcTransport, + CollectionDescriptor.ofMap(collectionName), + CollectionHandleDefaults.of(fn)); } /** diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/WeaviateCollectionsClientAsync.java b/src/main/java/io/weaviate/client6/v1/api/collections/WeaviateCollectionsClientAsync.java index d357d56cc..4fc449cf1 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/WeaviateCollectionsClientAsync.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/WeaviateCollectionsClientAsync.java @@ -22,8 +22,17 @@ public WeaviateCollectionsClientAsync(RestTransport restTransport, GrpcTransport } public CollectionHandleAsync> use(String collectionName) { - return new CollectionHandleAsync<>(restTransport, grpcTransport, - CollectionDescriptor.ofMap(collectionName)); + return use(collectionName, CollectionHandleDefaults.none()); + } + + public CollectionHandleAsync> use( + String collectionName, + Function> fn) { + return new CollectionHandleAsync<>( + restTransport, + grpcTransport, + CollectionDescriptor.ofMap(collectionName), + CollectionHandleDefaults.of(fn)); } public CompletableFuture create(String name) { 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 cb0771e0f..891db15e6 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 @@ -15,46 +15,54 @@ import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; import io.weaviate.client6.v1.internal.rest.RestTransport; -public class WeaviateDataClient { +public class WeaviateDataClient { private final RestTransport restTransport; private final GrpcTransport grpcTransport; - private final CollectionDescriptor collectionDescriptor; + private final CollectionDescriptor collectionDescriptor; - private final WeaviateQueryClient query; + private final WeaviateQueryClient query; - public WeaviateDataClient(CollectionDescriptor collectionDescriptor, RestTransport restTransport, - GrpcTransport grpcTransport) { + public WeaviateDataClient(CollectionDescriptor collectionDescriptor, RestTransport restTransport, + GrpcTransport grpcTransport, WeaviateQueryClient query) { this.restTransport = restTransport; this.grpcTransport = grpcTransport; this.collectionDescriptor = collectionDescriptor; - this.query = new WeaviateQueryClient<>(collectionDescriptor, grpcTransport); + this.query = query; + } + /** Copy constructor that updates the {@link #query} to use new defaults. */ + public WeaviateDataClient(WeaviateDataClient c, WeaviateQueryClient query) { + this.restTransport = c.restTransport; + this.grpcTransport = c.grpcTransport; + this.collectionDescriptor = c.collectionDescriptor; + this.query = query; } - public WeaviateObject insert(T properties) throws IOException { + public WeaviateObject insert(PropertiesT properties) throws IOException { return insert(InsertObjectRequest.of(collectionDescriptor.name(), properties)); } - public WeaviateObject insert(T properties, - Function, ObjectBuilder>> fn) + public WeaviateObject insert(PropertiesT properties, + Function, ObjectBuilder>> fn) throws IOException { return insert(InsertObjectRequest.of(collectionDescriptor.name(), properties, fn)); } @SafeVarargs - public final InsertManyResponse insertMany(T... objects) { + 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)); } - public InsertManyResponse insertMany(InsertManyRequest request) { + public InsertManyResponse insertMany(InsertManyRequest request) { return this.grpcTransport.performRequest(request, InsertManyRequest.rpc(request.objects(), collectionDescriptor)); } - public WeaviateObject insert(InsertObjectRequest request) throws IOException { + public WeaviateObject insert(InsertObjectRequest request) + throws IOException { return this.restTransport.performRequest(request, InsertObjectRequest.endpoint(collectionDescriptor)); } @@ -62,13 +70,15 @@ public boolean exists(String uuid) throws IOException { return this.query.byId(uuid).isPresent(); } - public void update(String uuid, Function, ObjectBuilder>> fn) + public void update(String uuid, + Function, ObjectBuilder>> fn) throws IOException { this.restTransport.performRequest(UpdateObjectRequest.of(collectionDescriptor.name(), uuid, fn), UpdateObjectRequest.endpoint(collectionDescriptor)); } - public void replace(String uuid, Function, ObjectBuilder>> fn) + public void replace(String uuid, + Function, ObjectBuilder>> fn) throws IOException { this.restTransport.performRequest(ReplaceObjectRequest.of(collectionDescriptor.name(), uuid, fn), ReplaceObjectRequest.endpoint(collectionDescriptor)); 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 506020b4b..197b0077d 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 @@ -18,46 +18,57 @@ import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; import io.weaviate.client6.v1.internal.rest.RestTransport; -public class WeaviateDataClientAsync { +public class WeaviateDataClientAsync { private final RestTransport restTransport; private final GrpcTransport grpcTransport; - private final CollectionDescriptor collectionDescriptor; + private final CollectionDescriptor collectionDescriptor; - private final WeaviateQueryClientAsync query; + private final WeaviateQueryClientAsync query; - public WeaviateDataClientAsync(CollectionDescriptor collectionDescriptor, RestTransport restTransport, - GrpcTransport grpcTransport) { + public WeaviateDataClientAsync(CollectionDescriptor collectionDescriptor, RestTransport restTransport, + GrpcTransport grpcTransport, WeaviateQueryClientAsync query) { this.restTransport = restTransport; this.grpcTransport = grpcTransport; this.collectionDescriptor = collectionDescriptor; - this.query = new WeaviateQueryClientAsync<>(collectionDescriptor, grpcTransport); + this.query = query; } - public CompletableFuture> insert(T properties) throws IOException { + /** Copy constructor that updates the {@link #query} to use new defaults. */ + public WeaviateDataClientAsync(WeaviateDataClientAsync c, WeaviateQueryClientAsync query) { + this.restTransport = c.restTransport; + this.grpcTransport = c.grpcTransport; + this.collectionDescriptor = c.collectionDescriptor; + this.query = query; + } + + public CompletableFuture> insert(PropertiesT properties) + throws IOException { return insert(InsertObjectRequest.of(collectionDescriptor.name(), properties)); } - public CompletableFuture> insert(T properties, - Function, ObjectBuilder>> fn) + public CompletableFuture> insert(PropertiesT properties, + Function, ObjectBuilder>> fn) throws IOException { return insert(InsertObjectRequest.of(collectionDescriptor.name(), properties, fn)); } - public CompletableFuture> insert(InsertObjectRequest request) + public CompletableFuture> insert( + InsertObjectRequest request) throws IOException { return this.restTransport.performRequestAsync(request, InsertObjectRequest.endpoint(collectionDescriptor)); } @SafeVarargs - public final CompletableFuture insertMany(T... objects) { + public final CompletableFuture insertMany(PropertiesT... objects) { return insertMany(InsertManyRequest.of(objects)); } - public CompletableFuture insertMany(List> objects) { + public CompletableFuture insertMany( + List> objects) { return insertMany(new InsertManyRequest<>(objects)); } - public CompletableFuture insertMany(InsertManyRequest request) { + public CompletableFuture insertMany(InsertManyRequest request) { return this.grpcTransport.performRequestAsync(request, InsertManyRequest.rpc(request.objects(), collectionDescriptor)); } @@ -67,14 +78,14 @@ public CompletableFuture exists(String uuid) { } public CompletableFuture update(String uuid, - Function, ObjectBuilder>> fn) + Function, ObjectBuilder>> fn) throws IOException { return this.restTransport.performRequestAsync(UpdateObjectRequest.of(collectionDescriptor.name(), uuid, fn), UpdateObjectRequest.endpoint(collectionDescriptor)); } public CompletableFuture replace(String uuid, - Function, ObjectBuilder>> fn) + Function, ObjectBuilder>> fn) throws IOException { return this.restTransport.performRequestAsync(ReplaceObjectRequest.of(collectionDescriptor.name(), uuid, fn), ReplaceObjectRequest.endpoint(collectionDescriptor)); 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 0db66bd6b..8867e55d1 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 @@ -4,6 +4,8 @@ import java.util.Optional; import java.util.function.Function; +import io.weaviate.client6.v1.api.collections.CollectionHandle; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; import io.weaviate.client6.v1.internal.ObjectBuilder; import io.weaviate.client6.v1.internal.grpc.GrpcTransport; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; @@ -12,9 +14,19 @@ abstract class AbstractQueryClient collection; protected final GrpcTransport grpcTransport; - AbstractQueryClient(CollectionDescriptor collection, GrpcTransport grpcTransport) { + private final CollectionHandleDefaults defaults; + + AbstractQueryClient(CollectionDescriptor collection, GrpcTransport grpcTransport, + CollectionHandleDefaults defaults) { this.collection = collection; this.grpcTransport = grpcTransport; + this.defaults = defaults; + } + + /** Copy constructor that sets new defaults. */ + AbstractQueryClient(AbstractQueryClient qc, + CollectionHandleDefaults defaults) { + this(qc.collection, qc.grpcTransport, defaults); } protected abstract SingleT byId(ById byId); @@ -23,6 +35,18 @@ abstract class AbstractQueryClient> Function> applyDefaults( + Function> fn) { + return ObjectBuilder.partial(fn, b -> b.consistencyLevel(defaults.consistencyLevel())); + } + // Fetch by ID -------------------------------------------------------------- public SingleT byId(String uuid) { @@ -30,9 +54,17 @@ public SingleT byId(String uuid) { } public SingleT byId(String uuid, Function> fn) { + // Collection handle defaults (consistencyLevel / tenant) are irrelevant for + // by-ID lookup. Do not `applyDefaults` to `fn`. return byId(ById.of(uuid, fn)); } + /** + * Retrieve the first result from query response if any. + * + * @param objects A list of objects, normally {@link QueryResponse#objects}. + * @return An object from the list or empty {@link Optional}. + */ protected final Optional optionalFirst(List objects) { return objects.isEmpty() ? Optional.empty() : Optional.ofNullable(objects.get(0)); } @@ -63,7 +95,7 @@ public ResponseT bm25(String query) { } public ResponseT bm25(String query, Function> fn) { - return bm25(Bm25.of(query, fn)); + return bm25(Bm25.of(query, applyDefaults(fn))); } public ResponseT bm25(Bm25 query) { @@ -75,7 +107,7 @@ public GroupedResponseT bm25(String query, GroupBy groupBy) { } public GroupedResponseT bm25(String query, Function> fn, GroupBy groupBy) { - return bm25(Bm25.of(query, fn), groupBy); + return bm25(Bm25.of(query, applyDefaults(fn)), groupBy); } public GroupedResponseT bm25(Bm25 query, GroupBy groupBy) { @@ -89,7 +121,7 @@ public ResponseT hybrid(String query) { } public ResponseT hybrid(String query, Function> fn) { - return hybrid(Hybrid.of(query, fn)); + return hybrid(Hybrid.of(query, applyDefaults(fn))); } public ResponseT hybrid(Hybrid query) { @@ -101,7 +133,7 @@ public GroupedResponseT hybrid(String query, GroupBy groupBy) { } public GroupedResponseT hybrid(String query, Function> fn, GroupBy groupBy) { - return hybrid(Hybrid.of(query, fn), groupBy); + return hybrid(Hybrid.of(query, applyDefaults(fn)), groupBy); } public GroupedResponseT hybrid(Hybrid query, GroupBy groupBy) { @@ -115,7 +147,7 @@ public ResponseT nearVector(float[] vector) { } public ResponseT nearVector(float[] vector, Function> fn) { - return nearVector(NearVector.of(vector, fn)); + return nearVector(NearVector.of(vector, applyDefaults(fn))); } public ResponseT nearVector(NearVector query) { @@ -128,7 +160,7 @@ public GroupedResponseT nearVector(float[] vector, GroupBy groupBy) { public GroupedResponseT nearVector(float[] vector, Function> fn, GroupBy groupBy) { - return nearVector(NearVector.of(vector, fn), groupBy); + return nearVector(NearVector.of(vector, applyDefaults(fn)), groupBy); } public GroupedResponseT nearVector(NearVector query, GroupBy groupBy) { @@ -142,7 +174,7 @@ public ResponseT nearObject(String uuid) { } public ResponseT nearObject(String uuid, Function> fn) { - return nearObject(NearObject.of(uuid, fn)); + return nearObject(NearObject.of(uuid, applyDefaults(fn))); } public ResponseT nearObject(NearObject query) { @@ -155,7 +187,7 @@ public GroupedResponseT nearObject(String uuid, GroupBy groupBy) { public GroupedResponseT nearObject(String uuid, Function> fn, GroupBy groupBy) { - return nearObject(NearObject.of(uuid, fn), groupBy); + return nearObject(NearObject.of(uuid, applyDefaults(fn)), groupBy); } public GroupedResponseT nearObject(NearObject query, GroupBy groupBy) { @@ -169,11 +201,11 @@ public ResponseT nearText(String... text) { } public ResponseT nearText(String text, Function> fn) { - return nearText(NearText.of(text, fn)); + return nearText(NearText.of(text, applyDefaults(fn))); } public ResponseT nearText(List text, Function> fn) { - return nearText(NearText.of(text, fn)); + return nearText(NearText.of(text, applyDefaults(fn))); } public ResponseT nearText(NearText query) { @@ -209,7 +241,7 @@ public ResponseT nearImage(String image) { } public ResponseT nearImage(String image, Function> fn) { - return nearImage(NearImage.of(image, fn)); + return nearImage(NearImage.of(image, applyDefaults(fn))); } public ResponseT nearImage(NearImage query) { @@ -222,7 +254,7 @@ public GroupedResponseT nearImage(String image, GroupBy groupBy) { public GroupedResponseT nearImage(String image, Function> fn, GroupBy groupBy) { - return nearImage(NearImage.of(image, fn), groupBy); + return nearImage(NearImage.of(image, applyDefaults(fn)), groupBy); } public GroupedResponseT nearImage(NearImage query, GroupBy groupBy) { @@ -236,7 +268,7 @@ public ResponseT nearAudio(String audio) { } public ResponseT nearAudio(String audio, Function> fn) { - return nearAudio(NearAudio.of(audio, fn)); + return nearAudio(NearAudio.of(audio, applyDefaults(fn))); } public ResponseT nearAudio(NearAudio query) { @@ -249,7 +281,7 @@ public GroupedResponseT nearAudio(String audio, GroupBy groupBy) { public GroupedResponseT nearAudio(String audio, Function> fn, GroupBy groupBy) { - return nearAudio(NearAudio.of(audio, fn), groupBy); + return nearAudio(NearAudio.of(audio, applyDefaults(fn)), groupBy); } public GroupedResponseT nearAudio(NearAudio query, GroupBy groupBy) { @@ -263,7 +295,7 @@ public ResponseT nearVideo(String video) { } public ResponseT nearVideo(String video, Function> fn) { - return nearVideo(NearVideo.of(video, fn)); + return nearVideo(NearVideo.of(video, applyDefaults(fn))); } public ResponseT nearVideo(NearVideo query) { @@ -276,7 +308,7 @@ public GroupedResponseT nearVideo(String video, GroupBy groupBy) { public GroupedResponseT nearVideo(String video, Function> fn, GroupBy groupBy) { - return nearVideo(NearVideo.of(video, fn), groupBy); + return nearVideo(NearVideo.of(video, applyDefaults(fn)), groupBy); } public GroupedResponseT nearVideo(NearVideo query, GroupBy groupBy) { @@ -290,7 +322,7 @@ public ResponseT nearThermal(String thermal) { } public ResponseT nearThermal(String thermal, Function> fn) { - return nearThermal(NearThermal.of(thermal, fn)); + return nearThermal(NearThermal.of(thermal, applyDefaults(fn))); } public ResponseT nearThermal(NearThermal query) { @@ -303,7 +335,7 @@ public GroupedResponseT nearThermal(String thermal, GroupBy groupBy) { public GroupedResponseT nearThermal(String thermal, Function> fn, GroupBy groupBy) { - return nearThermal(NearThermal.of(thermal, fn), groupBy); + return nearThermal(NearThermal.of(thermal, applyDefaults(fn)), groupBy); } public GroupedResponseT nearThermal(NearThermal query, GroupBy groupBy) { @@ -317,7 +349,7 @@ public ResponseT nearDepth(String depth) { } public ResponseT nearDepth(String depth, Function> fn) { - return nearDepth(NearDepth.of(depth, fn)); + return nearDepth(NearDepth.of(depth, applyDefaults(fn))); } public ResponseT nearDepth(NearDepth query) { @@ -330,7 +362,7 @@ public GroupedResponseT nearDepth(String depth, GroupBy groupBy) { public GroupedResponseT nearDepth(String depth, Function> fn, GroupBy groupBy) { - return nearDepth(NearDepth.of(depth, fn), groupBy); + return nearDepth(NearDepth.of(depth, applyDefaults(fn)), groupBy); } public GroupedResponseT nearDepth(NearDepth query, GroupBy groupBy) { @@ -344,7 +376,7 @@ public ResponseT nearImu(String imu) { } public ResponseT nearImu(String imu, Function> fn) { - return nearImu(NearImu.of(imu, fn)); + return nearImu(NearImu.of(imu, applyDefaults(fn))); } public ResponseT nearImu(NearImu query) { @@ -357,7 +389,7 @@ public GroupedResponseT nearImu(String imu, GroupBy groupBy) { public GroupedResponseT nearImu(String imu, Function> fn, GroupBy groupBy) { - return nearImu(NearImu.of(imu, fn), groupBy); + return nearImu(NearImu.of(imu, applyDefaults(fn)), groupBy); } public GroupedResponseT nearImu(NearImu query, GroupBy groupBy) { 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 54801ca12..1fc48e7a4 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 @@ -2,6 +2,7 @@ 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; @@ -10,8 +11,16 @@ public class WeaviateQueryClient extends AbstractQueryClient>, QueryResponse, QueryResponseGrouped> { - public WeaviateQueryClient(CollectionDescriptor collection, GrpcTransport grpcTransport) { - super(collection, grpcTransport); + public WeaviateQueryClient( + CollectionDescriptor collection, + GrpcTransport grpcTransport, + CollectionHandleDefaults defaults) { + super(collection, grpcTransport, defaults); + } + + /** Copy constructor that sets new defaults. */ + public WeaviateQueryClient(WeaviateQueryClient qc, CollectionHandleDefaults defaults) { + super(qc, defaults); } @Override 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 e8415314f..03c3fcbd5 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 @@ -3,6 +3,7 @@ import java.util.Optional; 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; @@ -11,8 +12,16 @@ public class WeaviateQueryClientAsync extends AbstractQueryClient>>, CompletableFuture>, CompletableFuture>> { - public WeaviateQueryClientAsync(CollectionDescriptor collection, GrpcTransport grpcTransport) { - super(collection, grpcTransport); + public WeaviateQueryClientAsync( + CollectionDescriptor collection, + GrpcTransport grpcTransport, + CollectionHandleDefaults defaults) { + super(collection, grpcTransport, defaults); + } + + /** Copy constructor that sets new defaults. */ + public WeaviateQueryClientAsync(WeaviateQueryClientAsync qc, CollectionHandleDefaults defaults) { + super(qc, defaults); } @Override diff --git a/src/test/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaultsTest.java b/src/test/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaultsTest.java new file mode 100644 index 000000000..1c1d1683f --- /dev/null +++ b/src/test/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaultsTest.java @@ -0,0 +1,52 @@ +package io.weaviate.client6.v1.api.collections; + +import java.util.Map; + +import org.assertj.core.api.Assertions; +import org.junit.Test; + +import io.weaviate.client6.v1.api.collections.query.ConsistencyLevel; +import io.weaviate.client6.v1.internal.ObjectBuilder; +import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; + +public class CollectionHandleDefaultsTest { + private static final CollectionDescriptor> DESCRIPTOR = CollectionDescriptor.ofMap("Things"); + + /** CollectionHandle with no defaults. */ + private static final CollectionHandle> HANDLE_NONE = new CollectionHandle<>( + null, null, + DESCRIPTOR, CollectionHandleDefaults.of(ObjectBuilder.identity())); + + /** CollectionHandleAsync with no defaults. */ + private static final CollectionHandleAsync> HANDLE_NONE_ASYNC = new CollectionHandleAsync<>( + null, null, + DESCRIPTOR, CollectionHandleDefaults.of(ObjectBuilder.identity())); + + /** All defaults are {@code null} if none were set. */ + @Test + public void test_defaults() { + Assertions.assertThat(HANDLE_NONE.consistencyLevel()).isNull(); + } + + /** + * {@link CollectionHandle#withConsistencyLevel} should create a copy with + * different defaults but not modify the original. + */ + @Test + public void test_withConsistencyLevel() { + var handle = HANDLE_NONE.withConsistencyLevel(ConsistencyLevel.QUORUM); + Assertions.assertThat(handle.consistencyLevel()).isEqualTo(ConsistencyLevel.QUORUM); + Assertions.assertThat(HANDLE_NONE.consistencyLevel()).isNull(); + } + + /** + * {@link CollectionHandleAsync#withConsistencyLevel} should create a copy with + * different defaults but not modify the original. + */ + @Test + public void test_withConsistencyLevel_async() { + var handle = HANDLE_NONE_ASYNC.withConsistencyLevel(ConsistencyLevel.QUORUM); + Assertions.assertThat(handle.consistencyLevel()).isEqualTo(ConsistencyLevel.QUORUM); + Assertions.assertThat(HANDLE_NONE_ASYNC.consistencyLevel()).isNull(); + } +} From ede84ab1a5f4c9b639c95ff146d333f3599ca20a Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 18 Aug 2025 13:25:43 +0200 Subject: [PATCH 02/24] fix: set consistencyLevel for pre-built QueryOperators E.g., when nearText is called with NearText.of() instead of a 'String queryTerm', consistencyLevel must be added on the RPC level. --- .../api/collections/query/AbstractQueryClient.java | 2 +- .../v1/api/collections/query/QueryOperator.java | 13 +++++++++++++ .../v1/api/collections/query/QueryRequest.java | 11 +++++++---- .../api/collections/query/WeaviateQueryClient.java | 6 +++--- .../collections/query/WeaviateQueryClientAsync.java | 6 +++--- 5 files changed, 27 insertions(+), 11 deletions(-) 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 8867e55d1..77f17c389 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 @@ -14,7 +14,7 @@ abstract class AbstractQueryClient collection; protected final GrpcTransport grpcTransport; - private final CollectionHandleDefaults defaults; + protected final CollectionHandleDefaults defaults; AbstractQueryClient(CollectionDescriptor collection, GrpcTransport grpcTransport, CollectionHandleDefaults defaults) { diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryOperator.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryOperator.java index d7a3e4bb2..204c83a1e 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryOperator.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryOperator.java @@ -1,7 +1,20 @@ package io.weaviate.client6.v1.api.collections.query; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoSearchGet; interface QueryOperator { + /** Append QueryOperator to the request message. */ void appendTo(WeaviateProtoSearchGet.SearchRequest.Builder req); + + /** + * Append QueryOperator to the request message and apply default parameters. + * Implementations generally shouldn't override this method. + */ + default void appendTo(WeaviateProtoSearchGet.SearchRequest.Builder req, CollectionHandleDefaults defaults) { + appendTo(req); + if (!req.hasConsistencyLevel() && defaults.consistencyLevel() != null) { + defaults.consistencyLevel().appendTo(req); + } + } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryRequest.java index 22ebbfa7c..84d216812 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryRequest.java @@ -9,6 +9,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +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; @@ -24,7 +25,8 @@ public record QueryRequest(QueryOperator operator, GroupBy groupBy) { static Rpc, WeaviateProtoSearchGet.SearchReply> rpc( - CollectionDescriptor collection) { + CollectionDescriptor collection, + CollectionHandleDefaults defaults) { return Rpc.of( request -> { var message = WeaviateProtoSearchGet.SearchRequest.newBuilder(); @@ -32,7 +34,7 @@ static Rpc Rpc Rpc, WeaviateProtoSearchGet.SearchReply> grouped( - CollectionDescriptor collection) { - var rpc = rpc(collection); + CollectionDescriptor collection, + CollectionHandleDefaults defaults) { + var rpc = rpc(collection, defaults); return Rpc.of( request -> rpc.marshal(request), reply -> { 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 1fc48e7a4..0a51731b9 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 @@ -26,7 +26,7 @@ public WeaviateQueryClient(WeaviateQueryClient qc, CollectionHandleDefaults d @Override protected Optional> byId(ById byId) { var request = new QueryRequest(byId, null); - var result = this.grpcTransport.performRequest(request, QueryRequest.rpc(collection)); + var result = this.grpcTransport.performRequest(request, QueryRequest.rpc(collection, defaults)); return optionalFirst(result.objects()); } @@ -34,13 +34,13 @@ protected Optional> byId(ById byId) { @Override protected final QueryResponse performRequest(QueryOperator operator) { var request = new QueryRequest(operator, null); - return this.grpcTransport.performRequest(request, QueryRequest.rpc(collection)); + return this.grpcTransport.performRequest(request, QueryRequest.rpc(collection, defaults)); } @Override protected final QueryResponseGrouped performRequest(QueryOperator operator, GroupBy groupBy) { var request = new QueryRequest(operator, groupBy); - return this.grpcTransport.performRequest(request, QueryRequest.grouped(collection)); + 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 03c3fcbd5..f971a39e0 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 @@ -28,20 +28,20 @@ public WeaviateQueryClientAsync(WeaviateQueryClientAsync qc, CollectionHandle protected CompletableFuture>> byId( ById byId) { var request = new QueryRequest(byId, null); - var result = this.grpcTransport.performRequestAsync(request, QueryRequest.rpc(collection)); + var result = this.grpcTransport.performRequestAsync(request, QueryRequest.rpc(collection, defaults)); return result.thenApply(r -> optionalFirst(r.objects())); } @Override protected final CompletableFuture> performRequest(QueryOperator operator) { var request = new QueryRequest(operator, null); - return this.grpcTransport.performRequestAsync(request, QueryRequest.rpc(collection)); + return this.grpcTransport.performRequestAsync(request, QueryRequest.rpc(collection, defaults)); } @Override protected final CompletableFuture> performRequest(QueryOperator operator, GroupBy groupBy) { var request = new QueryRequest(operator, groupBy); - return this.grpcTransport.performRequestAsync(request, QueryRequest.grouped(collection)); + return this.grpcTransport.performRequestAsync(request, QueryRequest.grouped(collection, defaults)); } } From ca05c311c01481dfcd7beae26a1290be47fa1cc6 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 18 Aug 2025 13:44:57 +0200 Subject: [PATCH 03/24] test: dry test setup --- .../v1/api/collections/CollectionHandleDefaultsTest.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/test/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaultsTest.java b/src/test/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaultsTest.java index 1c1d1683f..1c0d7aff2 100644 --- a/src/test/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaultsTest.java +++ b/src/test/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaultsTest.java @@ -11,16 +11,15 @@ public class CollectionHandleDefaultsTest { private static final CollectionDescriptor> DESCRIPTOR = CollectionDescriptor.ofMap("Things"); + private static final CollectionHandleDefaults NONE_DEFAULTS = CollectionHandleDefaults.of(ObjectBuilder.identity()); /** CollectionHandle with no defaults. */ private static final CollectionHandle> HANDLE_NONE = new CollectionHandle<>( - null, null, - DESCRIPTOR, CollectionHandleDefaults.of(ObjectBuilder.identity())); + null, null, DESCRIPTOR, NONE_DEFAULTS); /** CollectionHandleAsync with no defaults. */ private static final CollectionHandleAsync> HANDLE_NONE_ASYNC = new CollectionHandleAsync<>( - null, null, - DESCRIPTOR, CollectionHandleDefaults.of(ObjectBuilder.identity())); + null, null, DESCRIPTOR, NONE_DEFAULTS); /** All defaults are {@code null} if none were set. */ @Test From 4c881a59c405f2fd36e1d4f31d5b09ab98668ea3 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Tue, 19 Aug 2025 14:36:45 +0200 Subject: [PATCH 04/24] refactor: apply defaults at marshal --- .../query/AbstractQueryClient.java | 57 +++++++------------ 1 file changed, 22 insertions(+), 35 deletions(-) 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 77f17c389..b822c0d03 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 @@ -4,7 +4,6 @@ import java.util.Optional; import java.util.function.Function; -import io.weaviate.client6.v1.api.collections.CollectionHandle; import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; import io.weaviate.client6.v1.internal.ObjectBuilder; import io.weaviate.client6.v1.internal.grpc.GrpcTransport; @@ -35,18 +34,6 @@ abstract class AbstractQueryClient> Function> applyDefaults( - Function> fn) { - return ObjectBuilder.partial(fn, b -> b.consistencyLevel(defaults.consistencyLevel())); - } - // Fetch by ID -------------------------------------------------------------- public SingleT byId(String uuid) { @@ -95,7 +82,7 @@ public ResponseT bm25(String query) { } public ResponseT bm25(String query, Function> fn) { - return bm25(Bm25.of(query, applyDefaults(fn))); + return bm25(Bm25.of(query, fn)); } public ResponseT bm25(Bm25 query) { @@ -107,7 +94,7 @@ public GroupedResponseT bm25(String query, GroupBy groupBy) { } public GroupedResponseT bm25(String query, Function> fn, GroupBy groupBy) { - return bm25(Bm25.of(query, applyDefaults(fn)), groupBy); + return bm25(Bm25.of(query, fn), groupBy); } public GroupedResponseT bm25(Bm25 query, GroupBy groupBy) { @@ -121,7 +108,7 @@ public ResponseT hybrid(String query) { } public ResponseT hybrid(String query, Function> fn) { - return hybrid(Hybrid.of(query, applyDefaults(fn))); + return hybrid(Hybrid.of(query, fn)); } public ResponseT hybrid(Hybrid query) { @@ -133,7 +120,7 @@ public GroupedResponseT hybrid(String query, GroupBy groupBy) { } public GroupedResponseT hybrid(String query, Function> fn, GroupBy groupBy) { - return hybrid(Hybrid.of(query, applyDefaults(fn)), groupBy); + return hybrid(Hybrid.of(query, fn), groupBy); } public GroupedResponseT hybrid(Hybrid query, GroupBy groupBy) { @@ -147,7 +134,7 @@ public ResponseT nearVector(float[] vector) { } public ResponseT nearVector(float[] vector, Function> fn) { - return nearVector(NearVector.of(vector, applyDefaults(fn))); + return nearVector(NearVector.of(vector, fn)); } public ResponseT nearVector(NearVector query) { @@ -160,7 +147,7 @@ public GroupedResponseT nearVector(float[] vector, GroupBy groupBy) { public GroupedResponseT nearVector(float[] vector, Function> fn, GroupBy groupBy) { - return nearVector(NearVector.of(vector, applyDefaults(fn)), groupBy); + return nearVector(NearVector.of(vector, fn), groupBy); } public GroupedResponseT nearVector(NearVector query, GroupBy groupBy) { @@ -174,7 +161,7 @@ public ResponseT nearObject(String uuid) { } public ResponseT nearObject(String uuid, Function> fn) { - return nearObject(NearObject.of(uuid, applyDefaults(fn))); + return nearObject(NearObject.of(uuid, fn)); } public ResponseT nearObject(NearObject query) { @@ -187,7 +174,7 @@ public GroupedResponseT nearObject(String uuid, GroupBy groupBy) { public GroupedResponseT nearObject(String uuid, Function> fn, GroupBy groupBy) { - return nearObject(NearObject.of(uuid, applyDefaults(fn)), groupBy); + return nearObject(NearObject.of(uuid, fn), groupBy); } public GroupedResponseT nearObject(NearObject query, GroupBy groupBy) { @@ -201,11 +188,11 @@ public ResponseT nearText(String... text) { } public ResponseT nearText(String text, Function> fn) { - return nearText(NearText.of(text, applyDefaults(fn))); + return nearText(NearText.of(text, fn)); } public ResponseT nearText(List text, Function> fn) { - return nearText(NearText.of(text, applyDefaults(fn))); + return nearText(NearText.of(text, fn)); } public ResponseT nearText(NearText query) { @@ -241,7 +228,7 @@ public ResponseT nearImage(String image) { } public ResponseT nearImage(String image, Function> fn) { - return nearImage(NearImage.of(image, applyDefaults(fn))); + return nearImage(NearImage.of(image, fn)); } public ResponseT nearImage(NearImage query) { @@ -254,7 +241,7 @@ public GroupedResponseT nearImage(String image, GroupBy groupBy) { public GroupedResponseT nearImage(String image, Function> fn, GroupBy groupBy) { - return nearImage(NearImage.of(image, applyDefaults(fn)), groupBy); + return nearImage(NearImage.of(image, fn), groupBy); } public GroupedResponseT nearImage(NearImage query, GroupBy groupBy) { @@ -268,7 +255,7 @@ public ResponseT nearAudio(String audio) { } public ResponseT nearAudio(String audio, Function> fn) { - return nearAudio(NearAudio.of(audio, applyDefaults(fn))); + return nearAudio(NearAudio.of(audio, fn)); } public ResponseT nearAudio(NearAudio query) { @@ -281,7 +268,7 @@ public GroupedResponseT nearAudio(String audio, GroupBy groupBy) { public GroupedResponseT nearAudio(String audio, Function> fn, GroupBy groupBy) { - return nearAudio(NearAudio.of(audio, applyDefaults(fn)), groupBy); + return nearAudio(NearAudio.of(audio, fn), groupBy); } public GroupedResponseT nearAudio(NearAudio query, GroupBy groupBy) { @@ -295,7 +282,7 @@ public ResponseT nearVideo(String video) { } public ResponseT nearVideo(String video, Function> fn) { - return nearVideo(NearVideo.of(video, applyDefaults(fn))); + return nearVideo(NearVideo.of(video, fn)); } public ResponseT nearVideo(NearVideo query) { @@ -308,7 +295,7 @@ public GroupedResponseT nearVideo(String video, GroupBy groupBy) { public GroupedResponseT nearVideo(String video, Function> fn, GroupBy groupBy) { - return nearVideo(NearVideo.of(video, applyDefaults(fn)), groupBy); + return nearVideo(NearVideo.of(video, fn), groupBy); } public GroupedResponseT nearVideo(NearVideo query, GroupBy groupBy) { @@ -322,7 +309,7 @@ public ResponseT nearThermal(String thermal) { } public ResponseT nearThermal(String thermal, Function> fn) { - return nearThermal(NearThermal.of(thermal, applyDefaults(fn))); + return nearThermal(NearThermal.of(thermal, fn)); } public ResponseT nearThermal(NearThermal query) { @@ -335,7 +322,7 @@ public GroupedResponseT nearThermal(String thermal, GroupBy groupBy) { public GroupedResponseT nearThermal(String thermal, Function> fn, GroupBy groupBy) { - return nearThermal(NearThermal.of(thermal, applyDefaults(fn)), groupBy); + return nearThermal(NearThermal.of(thermal, fn), groupBy); } public GroupedResponseT nearThermal(NearThermal query, GroupBy groupBy) { @@ -349,7 +336,7 @@ public ResponseT nearDepth(String depth) { } public ResponseT nearDepth(String depth, Function> fn) { - return nearDepth(NearDepth.of(depth, applyDefaults(fn))); + return nearDepth(NearDepth.of(depth, fn)); } public ResponseT nearDepth(NearDepth query) { @@ -362,7 +349,7 @@ public GroupedResponseT nearDepth(String depth, GroupBy groupBy) { public GroupedResponseT nearDepth(String depth, Function> fn, GroupBy groupBy) { - return nearDepth(NearDepth.of(depth, applyDefaults(fn)), groupBy); + return nearDepth(NearDepth.of(depth, fn), groupBy); } public GroupedResponseT nearDepth(NearDepth query, GroupBy groupBy) { @@ -376,7 +363,7 @@ public ResponseT nearImu(String imu) { } public ResponseT nearImu(String imu, Function> fn) { - return nearImu(NearImu.of(imu, applyDefaults(fn))); + return nearImu(NearImu.of(imu, fn)); } public ResponseT nearImu(NearImu query) { @@ -389,7 +376,7 @@ public GroupedResponseT nearImu(String imu, GroupBy groupBy) { public GroupedResponseT nearImu(String imu, Function> fn, GroupBy groupBy) { - return nearImu(NearImu.of(imu, applyDefaults(fn)), groupBy); + return nearImu(NearImu.of(imu, fn), groupBy); } public GroupedResponseT nearImu(NearImu query, GroupBy groupBy) { From 239837cc78e033bc61a60e3662bba1287b763571 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Tue, 19 Aug 2025 14:56:47 +0200 Subject: [PATCH 05/24] feat: make delete/insertMany consistencyLevel-aware --- .../v1/api/collections/CollectionHandle.java | 4 ++-- .../collections/CollectionHandleAsync.java | 4 ++-- .../collections/data/DeleteManyRequest.java | 7 +++++- .../collections/data/InsertManyRequest.java | 8 ++++++- .../collections/data/WeaviateDataClient.java | 22 +++++++++++++------ .../data/WeaviateDataClientAsync.java | 21 ++++++++++++------ .../collections/query/ConsistencyLevel.java | 12 +++++++++- 7 files changed, 57 insertions(+), 21 deletions(-) diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandle.java b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandle.java index 4233da870..c5b081e02 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandle.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandle.java @@ -30,7 +30,7 @@ public CollectionHandle( this.config = new WeaviateConfigClient(collectionDescriptor, restTransport, grpcTransport); this.aggregate = new WeaviateAggregateClient(collectionDescriptor, grpcTransport); this.query = new WeaviateQueryClient<>(collectionDescriptor, grpcTransport, defaults); - this.data = new WeaviateDataClient<>(collectionDescriptor, restTransport, grpcTransport, query); + this.data = new WeaviateDataClient<>(collectionDescriptor, restTransport, grpcTransport, defaults); this.defaults = defaults; } @@ -40,7 +40,7 @@ private CollectionHandle(CollectionHandle c, CollectionHandleDefaul this.config = c.config; this.aggregate = c.aggregate; this.query = new WeaviateQueryClient<>(c.query, defaults); - this.data = new WeaviateDataClient<>(c.data, query); + this.data = new WeaviateDataClient<>(c.data, defaults); this.defaults = defaults; } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleAsync.java b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleAsync.java index 997067799..2cd669ebf 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleAsync.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleAsync.java @@ -33,7 +33,7 @@ public CollectionHandleAsync( this.config = new WeaviateConfigClientAsync(collectionDescriptor, restTransport, grpcTransport); this.aggregate = new WeaviateAggregateClientAsync(collectionDescriptor, grpcTransport); this.query = new WeaviateQueryClientAsync<>(collectionDescriptor, grpcTransport, defaults); - this.data = new WeaviateDataClientAsync<>(collectionDescriptor, restTransport, grpcTransport, query); + this.data = new WeaviateDataClientAsync<>(collectionDescriptor, restTransport, grpcTransport, defaults); this.defaults = defaults; } @@ -43,7 +43,7 @@ private CollectionHandleAsync(CollectionHandleAsync c, CollectionHa this.config = c.config; this.aggregate = c.aggregate; this.query = new WeaviateQueryClientAsync<>(c.query, defaults); - this.data = new WeaviateDataClientAsync<>(c.data, query); + this.data = new WeaviateDataClientAsync<>(c.data, defaults); this.defaults = defaults; } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteManyRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteManyRequest.java index fe4788481..e8067545f 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteManyRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteManyRequest.java @@ -2,6 +2,7 @@ import java.util.function.Function; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; import io.weaviate.client6.v1.api.collections.query.Where; import io.weaviate.client6.v1.internal.ObjectBuilder; import io.weaviate.client6.v1.internal.grpc.ByteStringUtil; @@ -15,7 +16,8 @@ public record DeleteManyRequest(Where where, Boolean verbose, Boolean dryRun) { public static Rpc rpc( - CollectionDescriptor collectionDescriptor) { + CollectionDescriptor collectionDescriptor, + CollectionHandleDefaults defaults) { return Rpc .of( request -> { @@ -28,6 +30,9 @@ public static Rpc InsertManyRequest of(T... properties) { public static Rpc, WeaviateProtoBatch.BatchObjectsRequest, InsertManyResponse, WeaviateProtoBatch.BatchObjectsReply> rpc( List> insertObjects, - CollectionDescriptor collectionsDescriptor) { + CollectionDescriptor collectionsDescriptor, + CollectionHandleDefaults defaults) { return Rpc.of( request -> { var message = WeaviateProtoBatch.BatchObjectsRequest.newBuilder(); @@ -48,6 +50,10 @@ public static Rpc, WeaviateProtoBatch.BatchObjectsReque return batchObject.build(); }).toList(); + if (defaults.consistencyLevel() != null) { + defaults.consistencyLevel().appendTo(message); + } + message.addAllObjects(batch); return message.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 891db15e6..e720f62b8 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 @@ -5,6 +5,7 @@ import java.util.List; 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; @@ -21,21 +22,27 @@ public class WeaviateDataClient { private final CollectionDescriptor collectionDescriptor; private final WeaviateQueryClient query; + private final CollectionHandleDefaults defaults; - public WeaviateDataClient(CollectionDescriptor collectionDescriptor, RestTransport restTransport, - GrpcTransport grpcTransport, WeaviateQueryClient query) { + public WeaviateDataClient( + CollectionDescriptor collectionDescriptor, + RestTransport restTransport, + GrpcTransport grpcTransport, + CollectionHandleDefaults defaults) { this.restTransport = restTransport; this.grpcTransport = grpcTransport; this.collectionDescriptor = collectionDescriptor; - this.query = query; + this.query = new WeaviateQueryClient<>(collectionDescriptor, grpcTransport, defaults); + this.defaults = defaults; } /** Copy constructor that updates the {@link #query} to use new defaults. */ - public WeaviateDataClient(WeaviateDataClient c, WeaviateQueryClient query) { + public WeaviateDataClient(WeaviateDataClient c, CollectionHandleDefaults defaults) { this.restTransport = c.restTransport; this.grpcTransport = c.grpcTransport; this.collectionDescriptor = c.collectionDescriptor; - this.query = query; + this.query = new WeaviateQueryClient<>(collectionDescriptor, grpcTransport, defaults); + this.defaults = defaults; } public WeaviateObject insert(PropertiesT properties) throws IOException { @@ -58,7 +65,8 @@ public InsertManyResponse insertMany(List request) { - return this.grpcTransport.performRequest(request, InsertManyRequest.rpc(request.objects(), collectionDescriptor)); + return this.grpcTransport.performRequest(request, + InsertManyRequest.rpc(request.objects(), collectionDescriptor, defaults)); } public WeaviateObject insert(InsertObjectRequest request) @@ -107,7 +115,7 @@ public DeleteManyResponse deleteMany(Where where, } public DeleteManyResponse deleteMany(DeleteManyRequest request) throws IOException { - return this.grpcTransport.performRequest(request, DeleteManyRequest.rpc(collectionDescriptor)); + return this.grpcTransport.performRequest(request, DeleteManyRequest.rpc(collectionDescriptor, defaults)); } public void referenceAdd(String fromUuid, String fromProperty, Reference reference) throws IOException { 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 197b0077d..7acd187c4 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,6 +8,7 @@ import java.util.concurrent.CompletableFuture; 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; @@ -24,21 +25,27 @@ public class WeaviateDataClientAsync { private final CollectionDescriptor collectionDescriptor; private final WeaviateQueryClientAsync query; + private final CollectionHandleDefaults defaults; - public WeaviateDataClientAsync(CollectionDescriptor collectionDescriptor, RestTransport restTransport, - GrpcTransport grpcTransport, WeaviateQueryClientAsync query) { + public WeaviateDataClientAsync( + CollectionDescriptor collectionDescriptor, + RestTransport restTransport, + GrpcTransport grpcTransport, + CollectionHandleDefaults defaults) { this.restTransport = restTransport; this.grpcTransport = grpcTransport; this.collectionDescriptor = collectionDescriptor; - this.query = query; + this.query = new WeaviateQueryClientAsync<>(collectionDescriptor, grpcTransport, defaults); + this.defaults = defaults; } /** Copy constructor that updates the {@link #query} to use new defaults. */ - public WeaviateDataClientAsync(WeaviateDataClientAsync c, WeaviateQueryClientAsync query) { + public WeaviateDataClientAsync(WeaviateDataClientAsync c, CollectionHandleDefaults defaults) { this.restTransport = c.restTransport; this.grpcTransport = c.grpcTransport; this.collectionDescriptor = c.collectionDescriptor; - this.query = query; + this.query = new WeaviateQueryClientAsync<>(collectionDescriptor, grpcTransport, defaults); + this.defaults = defaults; } public CompletableFuture> insert(PropertiesT properties) @@ -70,7 +77,7 @@ public CompletableFuture insertMany( public CompletableFuture insertMany(InsertManyRequest request) { return this.grpcTransport.performRequestAsync(request, - InsertManyRequest.rpc(request.objects(), collectionDescriptor)); + InsertManyRequest.rpc(request.objects(), collectionDescriptor, defaults)); } public CompletableFuture exists(String uuid) { @@ -114,7 +121,7 @@ public CompletableFuture deleteMany(Where where, } public CompletableFuture deleteMany(DeleteManyRequest request) throws IOException { - return this.grpcTransport.performRequestAsync(request, DeleteManyRequest.rpc(collectionDescriptor)); + return this.grpcTransport.performRequestAsync(request, DeleteManyRequest.rpc(collectionDescriptor, defaults)); } public CompletableFuture referenceAdd(String fromUuid, String fromProperty, Reference reference) { diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/ConsistencyLevel.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/ConsistencyLevel.java index 27cd30221..a73e38e45 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/ConsistencyLevel.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/ConsistencyLevel.java @@ -1,6 +1,8 @@ package io.weaviate.client6.v1.api.collections.query; import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBase; +import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBatch; +import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBatchDelete; import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoSearchGet; public enum ConsistencyLevel { @@ -14,7 +16,15 @@ public enum ConsistencyLevel { this.consistencyLevel = consistencyLevel; } - final void appendTo(WeaviateProtoSearchGet.SearchRequest.Builder req) { + public final void appendTo(WeaviateProtoSearchGet.SearchRequest.Builder req) { + req.setConsistencyLevel(consistencyLevel); + } + + public final void appendTo(WeaviateProtoBatchDelete.BatchDeleteRequest.Builder req) { + req.setConsistencyLevel(consistencyLevel); + } + + public final void appendTo(WeaviateProtoBatch.BatchObjectsRequest.Builder req) { req.setConsistencyLevel(consistencyLevel); } } From c35233041dc619512de5fd7e4348bbe69e959ee0 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Wed, 20 Aug 2025 12:45:01 +0200 Subject: [PATCH 06/24] feat: add default consistencyLevel to all methods in 'data' namespace --- .../collections/CollectionHandleDefaults.java | 168 ++++++++++++++++++ .../collections/data/DeleteManyRequest.java | 80 ++++----- .../collections/data/DeleteObjectRequest.java | 20 ++- .../collections/data/InsertManyRequest.java | 89 +++++----- .../collections/data/InsertObjectRequest.java | 27 +-- .../data/ReferenceAddManyRequest.java | 40 +++-- .../collections/data/ReferenceAddRequest.java | 19 +- .../data/ReferenceDeleteRequest.java | 18 +- .../data/ReferenceReplaceRequest.java | 18 +- .../data/ReplaceObjectRequest.java | 20 ++- .../collections/data/UpdateObjectRequest.java | 20 ++- .../collections/data/WeaviateDataClient.java | 49 +++-- .../data/WeaviateDataClientAsync.java | 68 ++++--- .../query/AbstractQueryClient.java | 10 +- .../collections/query/ConsistencyLevel.java | 15 +- .../query/WeaviateQueryClient.java | 2 +- .../query/WeaviateQueryClientAsync.java | 2 +- .../v1/internal/rest/BooleanEndpoint.java | 2 +- .../internal/rest/DefaultRestTransport.java | 25 +-- .../client6/v1/internal/rest/Endpoint.java | 2 +- .../v1/internal/rest/EndpointBase.java | 19 +- .../v1/internal/rest/OptionalEndpoint.java | 4 +- .../v1/internal/rest/SimpleEndpoint.java | 8 +- .../client6/v1/internal/rest/UrlEncoder.java | 27 +++ .../data/WeaviateDataClientTest.java | 164 +++++++++++++++++ .../client6/v1/internal/json/JSONTest.java | 1 + .../testutil/transport/MockGrpcTransport.java | 56 ++++++ .../testutil/transport/MockRestTransport.java | 55 ++++++ 28 files changed, 778 insertions(+), 250 deletions(-) create mode 100644 src/main/java/io/weaviate/client6/v1/internal/rest/UrlEncoder.java create mode 100644 src/test/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientTest.java create mode 100644 src/test/java/io/weaviate/testutil/transport/MockGrpcTransport.java create mode 100644 src/test/java/io/weaviate/testutil/transport/MockRestTransport.java diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java index b1b549d1e..88e6c467f 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java @@ -1,11 +1,26 @@ package io.weaviate.client6.v1.api.collections; +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiFunction; import java.util.function.Function; +import com.google.common.util.concurrent.ListenableFuture; + import io.weaviate.client6.v1.api.collections.query.ConsistencyLevel; import io.weaviate.client6.v1.internal.ObjectBuilder; +import io.weaviate.client6.v1.internal.grpc.Rpc; +import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateGrpc.WeaviateBlockingStub; +import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateGrpc.WeaviateFutureStub; +import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBatch; +import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBatchDelete; +import io.weaviate.client6.v1.internal.rest.Endpoint; +import io.weaviate.client6.v1.internal.rest.EndpointBase; +import io.weaviate.client6.v1.internal.rest.JsonEndpoint; public record CollectionHandleDefaults(ConsistencyLevel consistencyLevel) { + private static final String CONSISTENCY_LEVEL = "consistency_level"; + /** * Set default values for query / aggregation requests. * @@ -32,6 +47,7 @@ public CollectionHandleDefaults(Builder builder) { public static final class Builder implements ObjectBuilder { private ConsistencyLevel consistencyLevel; + /** Set default consistency level for this collection handle. */ public Builder consistencyLevel(ConsistencyLevel consistencyLevel) { this.consistencyLevel = consistencyLevel; return this; @@ -42,4 +58,156 @@ public CollectionHandleDefaults build() { return new CollectionHandleDefaults(this); } } + + public Endpoint endpoint(Endpoint ep, + Function, ObjectBuilder>> fn) { + return fn.apply(new EndpointBuilder<>(ep)).build(); + } + + public Rpc rpc( + Rpc rpc) { + return new ContextRpc<>(rpc); + } + + /** Which part of the request a parameter should be added to. */ + public static enum Location { + /** Query string. */ + QUERY, + /** + * Request body. {@code RequestT} must implement {@link WithDefaults} for the + * changes to be applied. + */ + BODY; + } + + public static interface WithDefaults> { + ConsistencyLevel consistencyLevel(); + + SelfT withConsistencyLevel(ConsistencyLevel consistencyLevel); + } + + private class ContextEndpoint extends EndpointBase + implements JsonEndpoint { + + private final Location consistencyLevelLoc; + private final Endpoint endpoint; + + ContextEndpoint(EndpointBuilder builder) { + super(builder.endpoint::method, + builder.endpoint::requestUrl, + builder.endpoint::queryParameters, + builder.endpoint::body); + this.consistencyLevelLoc = builder.consistencyLevelLoc; + this.endpoint = builder.endpoint; + } + + /** Return consistencyLevel of the enclosing CollectionHandleDefaults object. */ + private ConsistencyLevel consistencyLevel() { + return CollectionHandleDefaults.this.consistencyLevel; + } + + @Override + public Map queryParameters(RequestT request) { + // Copy the map, as it's most likely unmodifiable. + var query = new HashMap<>(super.queryParameters(request)); + if (consistencyLevel() != null && consistencyLevelLoc == Location.QUERY) { + query.putIfAbsent(CONSISTENCY_LEVEL, consistencyLevel()); + } + return query; + } + + @SuppressWarnings("unchecked") + @Override + public String body(RequestT request) { + if (request instanceof WithDefaults wd) { + if (wd.consistencyLevel() == null) { + wd = wd.withConsistencyLevel(consistencyLevel()); + } + // This cast is safe as long as `wd` returns its own type, + // which it does as per the interface contract. + request = (RequestT) wd; + } + return super.body(request); + } + + @Override + public ResponseT deserializeResponse(int statusCode, String responseBody) { + return EndpointBase.deserializeResponse(endpoint, statusCode, responseBody); + } + } + + /** + * EndpointBuilder configures how CollectionHandleDefautls + * are added to a REST request. + */ + public class EndpointBuilder implements ObjectBuilder> { + private final Endpoint endpoint; + + private Location consistencyLevelLoc; + + EndpointBuilder(Endpoint ep) { + this.endpoint = ep; + } + + /** Control which part of the request to add default consistency level to. */ + public EndpointBuilder consistencyLevel(Location loc) { + this.consistencyLevelLoc = loc; + return this; + } + + @Override + public Endpoint build() { + return new ContextEndpoint<>(this); + } + } + + private class ContextRpc + implements Rpc { + + private final Rpc rpc; + + ContextRpc(Rpc rpc) { + this.rpc = rpc; + } + + /** Return consistencyLevel of the enclosing CollectionHandleDefaults object. */ + private ConsistencyLevel consistencyLevel() { + return CollectionHandleDefaults.this.consistencyLevel; + } + + @SuppressWarnings("unchecked") + @Override + public RequestM marshal(RequestT request) { + var message = rpc.marshal(request); + if (message instanceof WeaviateProtoBatchDelete.BatchDeleteRequest msg) { + var b = msg.toBuilder(); + if (!msg.hasConsistencyLevel() && consistencyLevel() != null) { + consistencyLevel().appendTo(b); + return (RequestM) b.build(); + } + } else if (message instanceof WeaviateProtoBatch.BatchObjectsRequest msg) { + var b = msg.toBuilder(); + if (!msg.hasConsistencyLevel() && consistencyLevel() != null) { + consistencyLevel().appendTo(b); + return (RequestM) b.build(); + } + } + return message; + } + + @Override + public ResponseT unmarshal(ReplyM reply) { + return rpc.unmarshal(reply); + } + + @Override + public BiFunction method() { + return rpc.method(); + } + + @Override + public BiFunction> methodAsync() { + return rpc.methodAsync(); + } + } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteManyRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteManyRequest.java index e8067545f..5cbb64465 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteManyRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteManyRequest.java @@ -16,48 +16,46 @@ public record DeleteManyRequest(Where where, Boolean verbose, Boolean dryRun) { public static Rpc rpc( - CollectionDescriptor collectionDescriptor, + CollectionDescriptor collection, CollectionHandleDefaults defaults) { - return Rpc - .of( - request -> { - var message = WeaviateProtoBatchDelete.BatchDeleteRequest.newBuilder(); - message.setCollection(collectionDescriptor.name()); - - if (request.verbose != null) { - message.setVerbose(request.verbose); - } - if (request.dryRun != null) { - message.setDryRun(request.dryRun); - } - if (defaults.consistencyLevel() != null) { - defaults.consistencyLevel().appendTo(message); - } - - var filters = WeaviateProtoBase.Filters.newBuilder(); - request.where.appendTo(filters); - message.setFilters(filters); - - return message.build(); - }, - reply -> { - var objects = reply.getObjectsList() - .stream() - .map(obj -> new DeleteManyResponse.DeletedObject( - ByteStringUtil.decodeUuid(obj.getUuid()).toString(), - obj.getSuccessful(), - obj.getError())) - .toList(); - - return new DeleteManyResponse( - reply.getTook(), - reply.getFailed(), - reply.getMatches(), - reply.getSuccessful(), - objects); - }, - () -> WeaviateBlockingStub::batchDelete, - () -> WeaviateFutureStub::batchDelete); + return defaults.rpc( + Rpc + .of( + request -> { + var message = WeaviateProtoBatchDelete.BatchDeleteRequest.newBuilder(); + message.setCollection(collection.name()); + + if (request.verbose != null) { + message.setVerbose(request.verbose); + } + if (request.dryRun != null) { + message.setDryRun(request.dryRun); + } + + var filters = WeaviateProtoBase.Filters.newBuilder(); + request.where.appendTo(filters); + message.setFilters(filters); + + return message.build(); + }, + reply -> { + var objects = reply.getObjectsList() + .stream() + .map(obj -> new DeleteManyResponse.DeletedObject( + ByteStringUtil.decodeUuid(obj.getUuid()).toString(), + obj.getSuccessful(), + obj.getError())) + .toList(); + + return new DeleteManyResponse( + reply.getTook(), + reply.getFailed(), + reply.getMatches(), + reply.getSuccessful(), + objects); + }, + () -> WeaviateBlockingStub::batchDelete, + () -> WeaviateFutureStub::batchDelete)); } public static DeleteManyRequest of(Where where) { diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteObjectRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteObjectRequest.java index 217a27682..ecb2adb2d 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteObjectRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteObjectRequest.java @@ -2,13 +2,23 @@ import java.util.Collections; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults.Location; +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 DeleteObjectRequest(String collectionName, String uuid) { +public record DeleteObjectRequest(String uuid) { - public static final Endpoint _ENDPOINT = SimpleEndpoint.sideEffect( - request -> "DELETE", - request -> "/objects/" + request.collectionName + "/" + request.uuid, - request -> Collections.emptyMap()); + public static final Endpoint endpoint( + CollectionDescriptor collection, + CollectionHandleDefaults defaults) { + return defaults.endpoint( + SimpleEndpoint.sideEffect( + request -> "DELETE", + request -> "/objects/" + collection.name() + "/" + request.uuid, + request -> Collections.emptyMap()), + add -> add + .consistencyLevel(Location.QUERY)); + } } 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 062e720e0..d270fa336 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 @@ -40,53 +40,50 @@ public static Rpc, WeaviateProtoBatch.BatchObjectsReque List> insertObjects, CollectionDescriptor collectionsDescriptor, CollectionHandleDefaults defaults) { - return Rpc.of( - request -> { - var message = WeaviateProtoBatch.BatchObjectsRequest.newBuilder(); - - var batch = request.objects.stream().map(obj -> { - var batchObject = WeaviateProtoBatch.BatchObject.newBuilder(); - buildObject(batchObject, obj, collectionsDescriptor); - return batchObject.build(); - }).toList(); - - if (defaults.consistencyLevel() != null) { - defaults.consistencyLevel().appendTo(message); - } - - message.addAllObjects(batch); - return message.build(); - }, - response -> { - var insertErrors = response.getErrorsList(); - - var responses = new ArrayList(insertObjects.size()); - var errors = new ArrayList(insertErrors.size()); - var uuids = new ArrayList(); - - var failed = insertErrors.stream() - .collect(Collectors.toMap(err -> err.getIndex(), err -> err.getError())); - - var iter = insertObjects.listIterator(); - while (iter.hasNext()) { - var idx = iter.nextIndex(); - var next = iter.next(); - var uuid = next.metadata() != null ? next.metadata().uuid() : null; - - if (failed.containsKey(idx)) { - var err = failed.get(idx); - errors.add(err); - responses.add(new InsertManyResponse.InsertObject(uuid, false, err)); - } else { - uuids.add(uuid); - responses.add(new InsertManyResponse.InsertObject(uuid, true, null)); - } - } + return defaults.rpc( + Rpc.of( + request -> { + var message = WeaviateProtoBatch.BatchObjectsRequest.newBuilder(); + + var batch = request.objects.stream().map(obj -> { + var batchObject = WeaviateProtoBatch.BatchObject.newBuilder(); + buildObject(batchObject, obj, collectionsDescriptor); + return batchObject.build(); + }).toList(); + + message.addAllObjects(batch); + return message.build(); + }, + response -> { + var insertErrors = response.getErrorsList(); + + var responses = new ArrayList(insertObjects.size()); + var errors = new ArrayList(insertErrors.size()); + var uuids = new ArrayList(); + + var failed = insertErrors.stream() + .collect(Collectors.toMap(err -> err.getIndex(), err -> err.getError())); + + var iter = insertObjects.listIterator(); + while (iter.hasNext()) { + var idx = iter.nextIndex(); + var next = iter.next(); + var uuid = next.metadata() != null ? next.metadata().uuid() : null; + + if (failed.containsKey(idx)) { + var err = failed.get(idx); + errors.add(err); + responses.add(new InsertManyResponse.InsertObject(uuid, false, err)); + } else { + uuids.add(uuid); + responses.add(new InsertManyResponse.InsertObject(uuid, true, null)); + } + } - return new InsertManyResponse(response.getTook(), responses, uuids, errors); - }, - () -> WeaviateBlockingStub::batchObjects, - () -> WeaviateFutureStub::batchObjects); + return new InsertManyResponse(response.getTook(), responses, uuids, errors); + }, + () -> WeaviateBlockingStub::batchObjects, + () -> WeaviateFutureStub::batchObjects)); } public static void buildObject(WeaviateProtoBatch.BatchObject.Builder object, 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 b1b460b11..97fecddc8 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 @@ -5,6 +5,8 @@ import com.google.gson.reflect.TypeToken; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults.Location; import io.weaviate.client6.v1.api.collections.ObjectMetadata; import io.weaviate.client6.v1.api.collections.Vectors; import io.weaviate.client6.v1.api.collections.WeaviateObject; @@ -18,16 +20,20 @@ public record InsertObjectRequest(WeaviateObject Endpoint, WeaviateObject> endpoint( - CollectionDescriptor descriptor) { - return new SimpleEndpoint<>( - request -> "POST", - request -> "/objects/", - request -> Collections.emptyMap(), - request -> JSON.serialize(request.object, TypeToken.getParameterized( - WeaviateObject.class, descriptor.typeToken().getType(), Reference.class, ObjectMetadata.class)), - (statusCode, response) -> JSON.deserialize(response, - (TypeToken>) TypeToken.getParameterized( - WeaviateObject.class, descriptor.typeToken().getType(), Object.class, ObjectMetadata.class))); + CollectionDescriptor collection, + CollectionHandleDefaults defaults) { + return defaults.endpoint( + new SimpleEndpoint<>( + request -> "POST", + request -> "/objects/", + request -> Collections.emptyMap(), + request -> JSON.serialize(request.object, TypeToken.getParameterized( + WeaviateObject.class, collection.typeToken().getType(), Reference.class, ObjectMetadata.class)), + (statusCode, response) -> JSON.deserialize(response, + (TypeToken>) TypeToken.getParameterized( + WeaviateObject.class, collection.typeToken().getType(), Object.class, ObjectMetadata.class))), + add -> add + .consistencyLevel(Location.QUERY)); } public static InsertObjectRequest of(String collectionName, T properties) { @@ -72,4 +78,5 @@ public InsertObjectRequest build() { return new InsertObjectRequest<>(this); } } + } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceAddManyRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceAddManyRequest.java index 0530d23e9..72b673bba 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceAddManyRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceAddManyRequest.java @@ -4,6 +4,8 @@ import java.util.Collections; import java.util.List; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults.Location; import io.weaviate.client6.v1.internal.json.JSON; import io.weaviate.client6.v1.internal.rest.Endpoint; import io.weaviate.client6.v1.internal.rest.SimpleEndpoint; @@ -11,24 +13,28 @@ public record ReferenceAddManyRequest(List references) { public static final Endpoint endpoint( - List references) { - return new SimpleEndpoint<>( - request -> "POST", - request -> "/batch/references", - request -> Collections.emptyMap(), - request -> JSON.serialize(request.references), - (statusCode, response) -> { - var result = JSON.deserialize(response, ReferenceAddManyResponse.class); - var errors = new ArrayList(); + List references, + CollectionHandleDefaults defaults) { + return defaults.endpoint( + new SimpleEndpoint<>( + request -> "POST", + request -> "/batch/references", + request -> Collections.emptyMap(), + request -> JSON.serialize(request.references), + (statusCode, response) -> { + var result = JSON.deserialize(response, ReferenceAddManyResponse.class); + var errors = new ArrayList(); - for (var err : result.errors()) { - errors.add(new ReferenceAddManyResponse.BatchError( - err.message(), - references.get(err.referenceIndex()), - err.referenceIndex())); - } - return new ReferenceAddManyResponse(errors); - }); + for (var err : result.errors()) { + errors.add(new ReferenceAddManyResponse.BatchError( + err.message(), + references.get(err.referenceIndex()), + err.referenceIndex())); + } + return new ReferenceAddManyResponse(errors); + }), + add -> add + .consistencyLevel(Location.QUERY)); } } 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 5da29e0fe..5fea35c24 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 @@ -2,6 +2,8 @@ import java.util.Collections; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults.Location; import io.weaviate.client6.v1.internal.json.JSON; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; import io.weaviate.client6.v1.internal.rest.Endpoint; @@ -10,11 +12,16 @@ public record ReferenceAddRequest(String fromUuid, String fromProperty, Reference reference) { public static final Endpoint endpoint( - CollectionDescriptor descriptor) { - return SimpleEndpoint.sideEffect( - request -> "POST", - request -> "/objects/" + descriptor.name() + "/" + request.fromUuid + "/references/" + request.fromProperty, - request -> Collections.emptyMap(), - request -> JSON.serialize(request.reference)); + CollectionDescriptor descriptor, + CollectionHandleDefaults defautls) { + return defautls.endpoint( + SimpleEndpoint.sideEffect( + request -> "POST", + request -> "/objects/" + descriptor.name() + "/" + request.fromUuid + "/references/" + request.fromProperty, + request -> Collections.emptyMap(), + request -> JSON.serialize(request.reference)), + add -> add + .consistencyLevel(Location.QUERY)); + } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceDeleteRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceDeleteRequest.java index f7f037e23..5038e0812 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceDeleteRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceDeleteRequest.java @@ -2,6 +2,8 @@ import java.util.Collections; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults.Location; import io.weaviate.client6.v1.internal.json.JSON; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; import io.weaviate.client6.v1.internal.rest.Endpoint; @@ -10,11 +12,15 @@ public record ReferenceDeleteRequest(String fromUuid, String fromProperty, Reference reference) { public static final Endpoint endpoint( - CollectionDescriptor descriptor) { - return SimpleEndpoint.sideEffect( - request -> "DELETE", - request -> "/objects/" + descriptor.name() + "/" + request.fromUuid + "/references/" + request.fromProperty, - request -> Collections.emptyMap(), - request -> JSON.serialize(request.reference)); + CollectionDescriptor descriptor, + CollectionHandleDefaults defaults) { + return defaults.endpoint( + SimpleEndpoint.sideEffect( + request -> "DELETE", + request -> "/objects/" + descriptor.name() + "/" + request.fromUuid + "/references/" + request.fromProperty, + request -> Collections.emptyMap(), + request -> JSON.serialize(request.reference)), + add -> add + .consistencyLevel(Location.QUERY)); } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceReplaceRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceReplaceRequest.java index 746fe6966..8d8aaf1e2 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceReplaceRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceReplaceRequest.java @@ -3,6 +3,8 @@ import java.util.Collections; import java.util.List; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults.Location; import io.weaviate.client6.v1.internal.json.JSON; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; import io.weaviate.client6.v1.internal.rest.Endpoint; @@ -11,11 +13,15 @@ public record ReferenceReplaceRequest(String fromUuid, String fromProperty, Reference reference) { public static final Endpoint endpoint( - CollectionDescriptor descriptor) { - return SimpleEndpoint.sideEffect( - request -> "PUT", - request -> "/objects/" + descriptor.name() + "/" + request.fromUuid + "/references/" + request.fromProperty, - request -> Collections.emptyMap(), - request -> JSON.serialize(List.of(request.reference))); + CollectionDescriptor descriptor, + CollectionHandleDefaults defaults) { + return defaults.endpoint( + SimpleEndpoint.sideEffect( + request -> "PUT", + request -> "/objects/" + descriptor.name() + "/" + request.fromUuid + "/references/" + request.fromProperty, + request -> Collections.emptyMap(), + request -> JSON.serialize(List.of(request.reference))), + add -> add + .consistencyLevel(Location.QUERY)); } } 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 09704839b..1ecb5455c 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 @@ -5,6 +5,8 @@ import com.google.gson.reflect.TypeToken; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults.Location; import io.weaviate.client6.v1.api.collections.ObjectMetadata; import io.weaviate.client6.v1.api.collections.Vectors; import io.weaviate.client6.v1.api.collections.WeaviateObject; @@ -16,13 +18,17 @@ public record ReplaceObjectRequest(WeaviateObject object) { - static final Endpoint, Void> endpoint(CollectionDescriptor collectionDescriptor) { - return SimpleEndpoint.sideEffect( - request -> "PUT", - request -> "/objects/" + collectionDescriptor.name() + "/" + request.object.metadata().uuid(), - request -> Collections.emptyMap(), - request -> JSON.serialize(request.object, TypeToken.getParameterized( - WeaviateObject.class, collectionDescriptor.typeToken().getType(), Reference.class, ObjectMetadata.class))); + static final Endpoint, Void> endpoint(CollectionDescriptor collection, + CollectionHandleDefaults defaults) { + return defaults.endpoint( + SimpleEndpoint.sideEffect( + request -> "PUT", + request -> "/objects/" + collection.name() + "/" + request.object.metadata().uuid(), + request -> Collections.emptyMap(), + request -> JSON.serialize(request.object, TypeToken.getParameterized( + WeaviateObject.class, collection.typeToken().getType(), Reference.class, ObjectMetadata.class))), + add -> add + .consistencyLevel(Location.QUERY)); } public static ReplaceObjectRequest of(String collectionName, String uuid, 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 f1f64022d..28423c752 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 @@ -5,6 +5,8 @@ import com.google.gson.reflect.TypeToken; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults.Location; import io.weaviate.client6.v1.api.collections.ObjectMetadata; import io.weaviate.client6.v1.api.collections.Vectors; import io.weaviate.client6.v1.api.collections.WeaviateObject; @@ -16,13 +18,17 @@ public record UpdateObjectRequest(WeaviateObject object) { - static final Endpoint, Void> endpoint(CollectionDescriptor collectionDescriptor) { - return SimpleEndpoint.sideEffect( - request -> "PATCH", - request -> "/objects/" + collectionDescriptor.name() + "/" + request.object.metadata().uuid(), - request -> Collections.emptyMap(), - request -> JSON.serialize(request.object, TypeToken.getParameterized( - WeaviateObject.class, collectionDescriptor.typeToken().getType(), Reference.class, ObjectMetadata.class))); + static final Endpoint, Void> endpoint(CollectionDescriptor collection, + CollectionHandleDefaults defaults) { + return defaults.endpoint( + SimpleEndpoint.sideEffect( + request -> "PATCH", + request -> "/objects/" + collection.name() + "/" + request.object.metadata().uuid(), + request -> Collections.emptyMap(), + request -> JSON.serialize(request.object, TypeToken.getParameterized( + WeaviateObject.class, collection.typeToken().getType(), Reference.class, ObjectMetadata.class))), + add -> add + .consistencyLevel(Location.QUERY)); } public static UpdateObjectRequest of(String collectionName, String uuid, 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 e720f62b8..6cda6883c 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 @@ -19,7 +19,7 @@ public class WeaviateDataClient { private final RestTransport restTransport; private final GrpcTransport grpcTransport; - private final CollectionDescriptor collectionDescriptor; + private final CollectionDescriptor collection; private final WeaviateQueryClient query; private final CollectionHandleDefaults defaults; @@ -31,7 +31,7 @@ public WeaviateDataClient( CollectionHandleDefaults defaults) { this.restTransport = restTransport; this.grpcTransport = grpcTransport; - this.collectionDescriptor = collectionDescriptor; + this.collection = collectionDescriptor; this.query = new WeaviateQueryClient<>(collectionDescriptor, grpcTransport, defaults); this.defaults = defaults; } @@ -40,19 +40,19 @@ public WeaviateDataClient( public WeaviateDataClient(WeaviateDataClient c, CollectionHandleDefaults defaults) { this.restTransport = c.restTransport; this.grpcTransport = c.grpcTransport; - this.collectionDescriptor = c.collectionDescriptor; - this.query = new WeaviateQueryClient<>(collectionDescriptor, grpcTransport, defaults); + this.collection = c.collection; + this.query = new WeaviateQueryClient<>(collection, grpcTransport, defaults); this.defaults = defaults; } public WeaviateObject insert(PropertiesT properties) throws IOException { - return insert(InsertObjectRequest.of(collectionDescriptor.name(), properties)); + return insert(InsertObjectRequest.of(collection.name(), properties)); } public WeaviateObject insert(PropertiesT properties, Function, ObjectBuilder>> fn) throws IOException { - return insert(InsertObjectRequest.of(collectionDescriptor.name(), properties, fn)); + return insert(InsertObjectRequest.of(collection.name(), properties, fn)); } @SafeVarargs @@ -66,63 +66,62 @@ public InsertManyResponse insertMany(List request) { return this.grpcTransport.performRequest(request, - InsertManyRequest.rpc(request.objects(), collectionDescriptor, defaults)); + InsertManyRequest.rpc(request.objects(), collection, defaults)); } public WeaviateObject insert(InsertObjectRequest request) throws IOException { - return this.restTransport.performRequest(request, InsertObjectRequest.endpoint(collectionDescriptor)); + return this.restTransport.performRequest(request, InsertObjectRequest.endpoint(collection, defaults)); } - public boolean exists(String uuid) throws IOException { + public boolean exists(String uuid) { return this.query.byId(uuid).isPresent(); } public void update(String uuid, Function, ObjectBuilder>> fn) throws IOException { - this.restTransport.performRequest(UpdateObjectRequest.of(collectionDescriptor.name(), uuid, fn), - UpdateObjectRequest.endpoint(collectionDescriptor)); + this.restTransport.performRequest(UpdateObjectRequest.of(collection.name(), uuid, fn), + UpdateObjectRequest.endpoint(collection, defaults)); } public void replace(String uuid, Function, ObjectBuilder>> fn) throws IOException { - this.restTransport.performRequest(ReplaceObjectRequest.of(collectionDescriptor.name(), uuid, fn), - ReplaceObjectRequest.endpoint(collectionDescriptor)); + this.restTransport.performRequest(ReplaceObjectRequest.of(collection.name(), uuid, fn), + ReplaceObjectRequest.endpoint(collection, defaults)); } public void delete(String uuid) throws IOException { - this.restTransport.performRequest(new DeleteObjectRequest(collectionDescriptor.name(), uuid), - DeleteObjectRequest._ENDPOINT); + this.restTransport.performRequest(new DeleteObjectRequest(uuid), + DeleteObjectRequest.endpoint(collection, defaults)); } - public DeleteManyResponse deleteMany(String... uuids) throws IOException { + public DeleteManyResponse deleteMany(String... uuids) { var either = Arrays.stream(uuids) .map(uuid -> (WhereOperand) Where.uuid().eq(uuid)) .toList(); return deleteMany(DeleteManyRequest.of(Where.or(either))); } - public DeleteManyResponse deleteMany(Where where) throws IOException { + public DeleteManyResponse deleteMany(Where where) { return deleteMany(DeleteManyRequest.of(where)); } public DeleteManyResponse deleteMany(Where where, - Function> fn) - throws IOException { + Function> fn) { return deleteMany(DeleteManyRequest.of(where, fn)); } - public DeleteManyResponse deleteMany(DeleteManyRequest request) throws IOException { - return this.grpcTransport.performRequest(request, DeleteManyRequest.rpc(collectionDescriptor, defaults)); + public DeleteManyResponse deleteMany(DeleteManyRequest request) { + return this.grpcTransport.performRequest(request, DeleteManyRequest.rpc(collection, defaults)); } public void referenceAdd(String fromUuid, String fromProperty, Reference reference) throws IOException { for (var uuid : reference.uuids()) { var singleRef = new Reference(reference.collection(), uuid); this.restTransport.performRequest(new ReferenceAddRequest(fromUuid, fromProperty, singleRef), - ReferenceAddRequest.endpoint(collectionDescriptor)); + ReferenceAddRequest.endpoint(collection, defaults)); } } @@ -132,14 +131,14 @@ public ReferenceAddManyResponse referenceAddMany(BatchReference... references) t public ReferenceAddManyResponse referenceAddMany(List references) throws IOException { return this.restTransport.performRequest(new ReferenceAddManyRequest(references), - ReferenceAddManyRequest.endpoint(references)); + ReferenceAddManyRequest.endpoint(references, defaults)); } public void referenceDelete(String fromUuid, String fromProperty, Reference reference) throws IOException { for (var uuid : reference.uuids()) { var singleRef = new Reference(reference.collection(), uuid); this.restTransport.performRequest(new ReferenceDeleteRequest(fromUuid, fromProperty, singleRef), - ReferenceDeleteRequest.endpoint(collectionDescriptor)); + ReferenceDeleteRequest.endpoint(collection, defaults)); } } @@ -147,7 +146,7 @@ public void referenceReplace(String fromUuid, String fromProperty, Reference ref for (var uuid : reference.uuids()) { var singleRef = new Reference(reference.collection(), uuid); this.restTransport.performRequest(new ReferenceReplaceRequest(fromUuid, fromProperty, singleRef), - ReferenceReplaceRequest.endpoint(collectionDescriptor)); + ReferenceReplaceRequest.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 7acd187c4..f85696a5f 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 @@ -1,6 +1,5 @@ package io.weaviate.client6.v1.api.collections.data; -import java.io.IOException; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -22,7 +21,7 @@ public class WeaviateDataClientAsync { private final RestTransport restTransport; private final GrpcTransport grpcTransport; - private final CollectionDescriptor collectionDescriptor; + private final CollectionDescriptor collection; private final WeaviateQueryClientAsync query; private final CollectionHandleDefaults defaults; @@ -34,7 +33,7 @@ public WeaviateDataClientAsync( CollectionHandleDefaults defaults) { this.restTransport = restTransport; this.grpcTransport = grpcTransport; - this.collectionDescriptor = collectionDescriptor; + this.collection = collectionDescriptor; this.query = new WeaviateQueryClientAsync<>(collectionDescriptor, grpcTransport, defaults); this.defaults = defaults; } @@ -43,26 +42,23 @@ public WeaviateDataClientAsync( public WeaviateDataClientAsync(WeaviateDataClientAsync c, CollectionHandleDefaults defaults) { this.restTransport = c.restTransport; this.grpcTransport = c.grpcTransport; - this.collectionDescriptor = c.collectionDescriptor; - this.query = new WeaviateQueryClientAsync<>(collectionDescriptor, grpcTransport, defaults); + this.collection = c.collection; + this.query = new WeaviateQueryClientAsync<>(collection, grpcTransport, defaults); this.defaults = defaults; } - public CompletableFuture> insert(PropertiesT properties) - throws IOException { - return insert(InsertObjectRequest.of(collectionDescriptor.name(), properties)); + public CompletableFuture> insert(PropertiesT properties) { + return insert(InsertObjectRequest.of(collection.name(), properties)); } public CompletableFuture> insert(PropertiesT properties, - Function, ObjectBuilder>> fn) - throws IOException { - return insert(InsertObjectRequest.of(collectionDescriptor.name(), properties, fn)); + Function, ObjectBuilder>> fn) { + return insert(InsertObjectRequest.of(collection.name(), properties, fn)); } public CompletableFuture> insert( - InsertObjectRequest request) - throws IOException { - return this.restTransport.performRequestAsync(request, InsertObjectRequest.endpoint(collectionDescriptor)); + InsertObjectRequest request) { + return this.restTransport.performRequestAsync(request, InsertObjectRequest.endpoint(collection, defaults)); } @SafeVarargs @@ -77,7 +73,7 @@ public CompletableFuture insertMany( public CompletableFuture insertMany(InsertManyRequest request) { return this.grpcTransport.performRequestAsync(request, - InsertManyRequest.rpc(request.objects(), collectionDescriptor, defaults)); + InsertManyRequest.rpc(request.objects(), collection, defaults)); } public CompletableFuture exists(String uuid) { @@ -85,68 +81,64 @@ public CompletableFuture exists(String uuid) { } public CompletableFuture update(String uuid, - Function, ObjectBuilder>> fn) - throws IOException { - return this.restTransport.performRequestAsync(UpdateObjectRequest.of(collectionDescriptor.name(), uuid, fn), - UpdateObjectRequest.endpoint(collectionDescriptor)); + Function, ObjectBuilder>> fn) { + return this.restTransport.performRequestAsync(UpdateObjectRequest.of(collection.name(), uuid, fn), + UpdateObjectRequest.endpoint(collection, defaults)); } public CompletableFuture replace(String uuid, - Function, ObjectBuilder>> fn) - throws IOException { - return this.restTransport.performRequestAsync(ReplaceObjectRequest.of(collectionDescriptor.name(), uuid, fn), - ReplaceObjectRequest.endpoint(collectionDescriptor)); + Function, ObjectBuilder>> fn) { + return this.restTransport.performRequestAsync(ReplaceObjectRequest.of(collection.name(), uuid, fn), + ReplaceObjectRequest.endpoint(collection, defaults)); } public CompletableFuture delete(String uuid) { - return this.restTransport.performRequestAsync(new DeleteObjectRequest(collectionDescriptor.name(), uuid), - DeleteObjectRequest._ENDPOINT); + return this.restTransport.performRequestAsync(new DeleteObjectRequest(uuid), + DeleteObjectRequest.endpoint(collection, defaults)); } - public CompletableFuture deleteMany(String... uuids) throws IOException { + public CompletableFuture deleteMany(String... uuids) { var either = Arrays.stream(uuids) .map(uuid -> (WhereOperand) Where.uuid().eq(uuid)) .toList(); return deleteMany(DeleteManyRequest.of(Where.or(either))); } - public CompletableFuture deleteMany(Where where) throws IOException { + public CompletableFuture deleteMany(Where where) { return deleteMany(DeleteManyRequest.of(where)); } public CompletableFuture deleteMany(Where where, - Function> fn) - throws IOException { + Function> fn) { return deleteMany(DeleteManyRequest.of(where, fn)); } - public CompletableFuture deleteMany(DeleteManyRequest request) throws IOException { - return this.grpcTransport.performRequestAsync(request, DeleteManyRequest.rpc(collectionDescriptor, defaults)); + public CompletableFuture deleteMany(DeleteManyRequest request) { + return this.grpcTransport.performRequestAsync(request, DeleteManyRequest.rpc(collection, defaults)); } public CompletableFuture referenceAdd(String fromUuid, String fromProperty, Reference reference) { return forEachAsync(reference.uuids(), uuid -> { var singleRef = new Reference(reference.collection(), (String) uuid); return this.restTransport.performRequestAsync(new ReferenceAddRequest(fromUuid, fromProperty, singleRef), - ReferenceAddRequest.endpoint(collectionDescriptor)); + ReferenceAddRequest.endpoint(collection, defaults)); }); } - public CompletableFuture referenceAddMany(BatchReference... references) throws IOException { + public CompletableFuture referenceAddMany(BatchReference... references) { return referenceAddMany(Arrays.asList(references)); } - public CompletableFuture referenceAddMany(List references) - throws IOException { + public CompletableFuture referenceAddMany(List references) { return this.restTransport.performRequestAsync(new ReferenceAddManyRequest(references), - ReferenceAddManyRequest.endpoint(references)); + ReferenceAddManyRequest.endpoint(references, defaults)); } public CompletableFuture referenceDelete(String fromUuid, String fromProperty, Reference reference) { return forEachAsync(reference.uuids(), uuid -> { var singleRef = new Reference(reference.collection(), (String) uuid); return this.restTransport.performRequestAsync(new ReferenceDeleteRequest(fromUuid, fromProperty, singleRef), - ReferenceDeleteRequest.endpoint(collectionDescriptor)); + ReferenceDeleteRequest.endpoint(collection, defaults)); }); } @@ -154,7 +146,7 @@ public CompletableFuture referenceReplace(String fromUuid, String fromProp return forEachAsync(reference.uuids(), uuid -> { var singleRef = new Reference(reference.collection(), (String) uuid); return this.restTransport.performRequestAsync(new ReferenceReplaceRequest(fromUuid, fromProperty, singleRef), - ReferenceReplaceRequest.endpoint(collectionDescriptor)); + ReferenceReplaceRequest.endpoint(collection, defaults)); }); } 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 b822c0d03..589a7f685 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 @@ -5,6 +5,7 @@ import java.util.function.Function; 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; @@ -49,11 +50,14 @@ public SingleT byId(String uuid, Function> fn) /** * Retrieve the first result from query response if any. * - * @param objects A list of objects, normally {@link QueryResponse#objects}. + * @param response Query response. * @return An object from the list or empty {@link Optional}. */ - protected final Optional optionalFirst(List objects) { - return objects.isEmpty() ? Optional.empty() : Optional.ofNullable(objects.get(0)); + protected final Optional> optionalFirst(QueryResponse response) { + return response == null || response.objects().isEmpty() + ? Optional.empty() + : Optional.ofNullable(response.objects().get(0)); + } // Object queries ----------------------------------------------------------- diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/ConsistencyLevel.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/ConsistencyLevel.java index a73e38e45..5ed88258f 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/ConsistencyLevel.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/ConsistencyLevel.java @@ -6,14 +6,16 @@ import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoSearchGet; public enum ConsistencyLevel { - ONE(WeaviateProtoBase.ConsistencyLevel.CONSISTENCY_LEVEL_ONE), - QUORUM(WeaviateProtoBase.ConsistencyLevel.CONSISTENCY_LEVEL_ONE), - ALL(WeaviateProtoBase.ConsistencyLevel.CONSISTENCY_LEVEL_ONE); + ONE(WeaviateProtoBase.ConsistencyLevel.CONSISTENCY_LEVEL_ONE, "ONE"), + QUORUM(WeaviateProtoBase.ConsistencyLevel.CONSISTENCY_LEVEL_ONE, "QUORUM"), + ALL(WeaviateProtoBase.ConsistencyLevel.CONSISTENCY_LEVEL_ONE, "ALL"); private final WeaviateProtoBase.ConsistencyLevel consistencyLevel; + private final String queryParameter; - ConsistencyLevel(WeaviateProtoBase.ConsistencyLevel consistencyLevel) { + ConsistencyLevel(WeaviateProtoBase.ConsistencyLevel consistencyLevel, String queryParameter) { this.consistencyLevel = consistencyLevel; + this.queryParameter = queryParameter; } public final void appendTo(WeaviateProtoSearchGet.SearchRequest.Builder req) { @@ -27,4 +29,9 @@ public final void appendTo(WeaviateProtoBatchDelete.BatchDeleteRequest.Builder r public final void appendTo(WeaviateProtoBatch.BatchObjectsRequest.Builder req) { req.setConsistencyLevel(consistencyLevel); } + + @Override + public String toString() { + return queryParameter; + } } 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 0a51731b9..b80640b4a 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 @@ -27,7 +27,7 @@ public WeaviateQueryClient(WeaviateQueryClient qc, CollectionHandleDefaults d protected Optional> byId(ById byId) { var request = new QueryRequest(byId, null); var result = this.grpcTransport.performRequest(request, QueryRequest.rpc(collection, defaults)); - return optionalFirst(result.objects()); + 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 f971a39e0..0c195e80d 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 @@ -29,7 +29,7 @@ protected CompletableFuture>> ById byId) { var request = new QueryRequest(byId, null); var result = this.grpcTransport.performRequestAsync(request, QueryRequest.rpc(collection, defaults)); - return result.thenApply(r -> optionalFirst(r.objects())); + return result.thenApply(this::optionalFirst); } @Override diff --git a/src/main/java/io/weaviate/client6/v1/internal/rest/BooleanEndpoint.java b/src/main/java/io/weaviate/client6/v1/internal/rest/BooleanEndpoint.java index b0b20665e..a4e29b20f 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/rest/BooleanEndpoint.java +++ b/src/main/java/io/weaviate/client6/v1/internal/rest/BooleanEndpoint.java @@ -8,7 +8,7 @@ public class BooleanEndpoint extends EndpointBase { public BooleanEndpoint( Function method, Function requestUrl, - Function> queryParameters, + Function> queryParameters, Function body) { super(method, requestUrl, queryParameters, body); } diff --git a/src/main/java/io/weaviate/client6/v1/internal/rest/DefaultRestTransport.java b/src/main/java/io/weaviate/client6/v1/internal/rest/DefaultRestTransport.java index bcd5a07ab..99d5bcb42 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/rest/DefaultRestTransport.java +++ b/src/main/java/io/weaviate/client6/v1/internal/rest/DefaultRestTransport.java @@ -75,6 +75,12 @@ public DefaultRestTransport(RestTransportOptions transportOptions) { this.httpClientAsync.start(); } + private String uri(Endpoint ep, RequestT req) { + return transportOptions.baseUrl() + + ep.requestUrl(req) + + UrlEncoder.encodeQuery(ep.queryParameters(req)); + } + @Override public ResponseT performRequest(RequestT request, Endpoint endpoint) @@ -86,7 +92,7 @@ public ResponseT performRequest(RequestT reque private ClassicHttpRequest prepareClassicRequest(RequestT request, Endpoint endpoint) { var method = endpoint.method(request); - var uri = transportOptions.baseUrl() + endpoint.requestUrl(request); + var uri = uri(endpoint, request); // TODO: apply options; var req = ClassicRequestBuilder.create(method).setUri(uri); @@ -138,8 +144,7 @@ public void cancelled() { private SimpleHttpRequest prepareSimpleRequest(RequestT request, Endpoint endpoint) { var method = endpoint.method(request); - var uri = transportOptions.baseUrl() + endpoint.requestUrl(request); - // TODO: apply options; + var uri = uri(endpoint, request); var body = endpoint.body(request); var req = SimpleHttpRequest.create(method, uri); @@ -166,19 +171,7 @@ private ResponseT _handleResponse(Endpoint endpoint, S var message = endpoint.deserializeError(statusCode, body); throw WeaviateApiException.http(method, url, statusCode, message); } - - if (endpoint instanceof JsonEndpoint json) { - @SuppressWarnings("unchecked") - ResponseT response = (ResponseT) json.deserializeResponse(statusCode, body); - return response; - } else if (endpoint instanceof BooleanEndpoint bool) { - @SuppressWarnings("unchecked") - ResponseT response = (ResponseT) ((Boolean) bool.getResult(statusCode)); - return response; - } - - // TODO: make it a WeaviateTransportException - throw new RuntimeException("Unhandled endpoint type " + endpoint.getClass().getSimpleName()); + return EndpointBase.deserializeResponse(endpoint, statusCode, body); } @Override diff --git a/src/main/java/io/weaviate/client6/v1/internal/rest/Endpoint.java b/src/main/java/io/weaviate/client6/v1/internal/rest/Endpoint.java index 52cc37c3b..6e1e33760 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/rest/Endpoint.java +++ b/src/main/java/io/weaviate/client6/v1/internal/rest/Endpoint.java @@ -10,7 +10,7 @@ public interface Endpoint { String body(RequestT request); - Map queryParameters(RequestT request); + Map queryParameters(RequestT request); /** Should this status code be considered an error? */ boolean isError(int statusCode); diff --git a/src/main/java/io/weaviate/client6/v1/internal/rest/EndpointBase.java b/src/main/java/io/weaviate/client6/v1/internal/rest/EndpointBase.java index 2ebe61d6d..d38622915 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/rest/EndpointBase.java +++ b/src/main/java/io/weaviate/client6/v1/internal/rest/EndpointBase.java @@ -14,7 +14,7 @@ public abstract class EndpointBase implements Endpoint method; protected final Function requestUrl; protected final Function body; - protected final Function> queryParameters; + protected final Function> queryParameters; @SuppressWarnings("unchecked") protected static Function nullBody() { @@ -24,7 +24,7 @@ protected static Function nullBody() { public EndpointBase( Function method, Function requestUrl, - Function> queryParameters, + Function> queryParameters, Function body) { this.method = method; this.requestUrl = requestUrl; @@ -43,7 +43,7 @@ public String requestUrl(RequestT request) { } @Override - public Map queryParameters(RequestT request) { + public Map queryParameters(RequestT request) { return queryParameters.apply(request); } @@ -67,6 +67,19 @@ public String deserializeError(int statusCode, String responseBody) { return response.errors.get(0).text(); } + @SuppressWarnings("unchecked") + public static ResponseT deserializeResponse(Endpoint endpoint, int statusCode, + String responseBody) { + if (endpoint instanceof JsonEndpoint json) { + return (ResponseT) json.deserializeResponse(statusCode, responseBody); + } else if (endpoint instanceof BooleanEndpoint bool) { + return (ResponseT) ((Boolean) bool.getResult(statusCode)); + } + + // TODO: make it a WeaviateTransportException + throw new RuntimeException("Unhandled endpoint type " + endpoint.getClass().getSimpleName()); + } + static record ErrorResponse(@SerializedName("error") List errors) { private static record ErrorMessage(@SerializedName("message") String text) { } diff --git a/src/main/java/io/weaviate/client6/v1/internal/rest/OptionalEndpoint.java b/src/main/java/io/weaviate/client6/v1/internal/rest/OptionalEndpoint.java index 0b6052573..c3863bf97 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/rest/OptionalEndpoint.java +++ b/src/main/java/io/weaviate/client6/v1/internal/rest/OptionalEndpoint.java @@ -10,7 +10,7 @@ public class OptionalEndpoint extends SimpleEndpoint OptionalEndpoint noBodyOptional( Function method, Function requestUrl, - Function> queryParameters, + Function> queryParameters, BiFunction deserializeResponse) { return new OptionalEndpoint<>(method, requestUrl, queryParameters, nullBody(), deserializeResponse); } @@ -18,7 +18,7 @@ public static OptionalEndpoint noBody public OptionalEndpoint( Function method, Function requestUrl, - Function> queryParameters, + Function> queryParameters, Function body, BiFunction deserializeResponse) { super(method, requestUrl, queryParameters, body, optional(deserializeResponse)); diff --git a/src/main/java/io/weaviate/client6/v1/internal/rest/SimpleEndpoint.java b/src/main/java/io/weaviate/client6/v1/internal/rest/SimpleEndpoint.java index 9f5c6fa9c..963cf4e3a 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/rest/SimpleEndpoint.java +++ b/src/main/java/io/weaviate/client6/v1/internal/rest/SimpleEndpoint.java @@ -17,7 +17,7 @@ protected static BiFunction nullResponse() { public static SimpleEndpoint noBody( Function method, Function requestUrl, - Function> queryParameters, + Function> queryParameters, BiFunction deserializeResponse) { return new SimpleEndpoint<>(method, requestUrl, queryParameters, nullBody(), deserializeResponse); } @@ -25,7 +25,7 @@ public static SimpleEndpoint noBody( public static SimpleEndpoint sideEffect( Function method, Function requestUrl, - Function> queryParameters, + Function> queryParameters, Function body) { return new SimpleEndpoint<>(method, requestUrl, queryParameters, body, nullResponse()); } @@ -33,14 +33,14 @@ public static SimpleEndpoint sideEffect( public static SimpleEndpoint sideEffect( Function method, Function requestUrl, - Function> queryParameters) { + Function> queryParameters) { return new SimpleEndpoint<>(method, requestUrl, queryParameters, nullBody(), nullResponse()); } public SimpleEndpoint( Function method, Function requestUrl, - Function> queryParameters, + Function> queryParameters, Function body, BiFunction deserializeResponse) { super(method, requestUrl, queryParameters, body); diff --git a/src/main/java/io/weaviate/client6/v1/internal/rest/UrlEncoder.java b/src/main/java/io/weaviate/client6/v1/internal/rest/UrlEncoder.java new file mode 100644 index 000000000..9c0f5f6ee --- /dev/null +++ b/src/main/java/io/weaviate/client6/v1/internal/rest/UrlEncoder.java @@ -0,0 +1,27 @@ +package io.weaviate.client6.v1.internal.rest; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.stream.Collectors; + +public final class UrlEncoder { + + private static String encodeValue(Object value) { + try { + return URLEncoder.encode(value.toString(), StandardCharsets.UTF_8.toString()); + } catch (UnsupportedEncodingException e) { + throw new AssertionError(e); // should never happen with a standard encoding + } + } + + public static String encodeQuery(Map queryParams) { + if (queryParams == null || queryParams.isEmpty()) { + return ""; + } + return queryParams.entrySet().stream() + .map(qp -> qp.getKey() + "=" + encodeValue(qp.getValue())) + .collect(Collectors.joining("&", "?", "")); + } +} diff --git a/src/test/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientTest.java b/src/test/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientTest.java new file mode 100644 index 000000000..0e9ae3baa --- /dev/null +++ b/src/test/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientTest.java @@ -0,0 +1,164 @@ +package io.weaviate.client6.v1.api.collections.data; + +import java.util.Map; + +import org.assertj.core.api.Assertions; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; + +import com.google.gson.JsonParser; +import com.jparams.junit4.JParamsTestRunner; +import com.jparams.junit4.data.DataMethod; +import com.jparams.junit4.description.Name; + +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults.Location; +import io.weaviate.client6.v1.api.collections.query.ConsistencyLevel; +import io.weaviate.client6.v1.internal.ObjectBuilder; +import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBase; +import io.weaviate.client6.v1.internal.json.JSON; +import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; +import io.weaviate.testutil.transport.MockGrpcTransport; +import io.weaviate.testutil.transport.MockRestTransport; + +@RunWith(JParamsTestRunner.class) +public class WeaviateDataClientTest { + private static MockRestTransport rest; + private static MockGrpcTransport grpc; + + @BeforeClass + public static void setUp() { + rest = new MockRestTransport(); + grpc = new MockGrpcTransport(); + } + + @AfterClass + public static void tearDown() throws Exception { + rest.close(); + grpc.close(); + } + + @FunctionalInterface + interface Act { + void apply(WeaviateDataClient> client) throws Exception; + } + + public static Object[][] restTestCases() { + return new Object[][] { + { + "insert single object", + ConsistencyLevel.ONE, Location.QUERY, + (Act) client -> client.insert(Map.of()), + }, + { + "replace single object", + ConsistencyLevel.ONE, Location.QUERY, + (Act) client -> client.replace("test-uuid", ObjectBuilder.identity()), + }, + { + "update single object", + ConsistencyLevel.ONE, Location.QUERY, + (Act) client -> client.update("test-uuid", ObjectBuilder.identity()), + }, + { + "delete by id", + ConsistencyLevel.ONE, Location.QUERY, + (Act) client -> client.delete("test-uuid"), + }, + { + "add reference", + ConsistencyLevel.ONE, Location.QUERY, + (Act) client -> client.referenceAdd("from-uuid", "from_property", Reference.uuids("to-uuid")), + }, + { + "add reference many", + ConsistencyLevel.ONE, Location.QUERY, + (Act) client -> client.referenceAddMany(), + }, + { + "replace reference", + ConsistencyLevel.ONE, Location.QUERY, + (Act) client -> client.referenceReplace("from-uuid", "from_property", Reference.uuids("to-uuid")), + }, + { + "delete reference", + ConsistencyLevel.ONE, Location.QUERY, + (Act) client -> client.referenceDelete("from-uuid", "from_property", Reference.uuids("to-uuid")), + }, + }; + } + + @Name("0") + @DataMethod(source = WeaviateDataClientTest.class, method = "restTestCases") + @Test + public void test_collectionHandleDefaults_rest(String __, ConsistencyLevel cl, Location clLoc, Act act) + throws Exception { + // Arrange + var collection = CollectionDescriptor.ofMap("Things"); + var defaults = new CollectionHandleDefaults(cl); + var client = new WeaviateDataClient>( + collection, rest, null, defaults); + + // Act + act.apply(client); + + // Assert + rest.assertNext((method, requestUrl, body, query) -> { + switch (clLoc) { + case QUERY: + Assertions.assertThat(query).containsEntry("consistency_level", defaults.consistencyLevel()); + break; + case BODY: + assertJsonHasValue(body, "consistency_level", defaults.consistencyLevel()); + } + }); + } + + private void assertJsonHasValue(String json, String key, T value) { + var gotJson = JsonParser.parseString(json).getAsJsonObject(); + Assertions.assertThat(gotJson.has(key)) + .describedAs("missing key \"%s\" in %s", key, json) + .isTrue(); + + var wantValue = JsonParser.parseString(JSON.serialize(value)); + Assertions.assertThat(gotJson.get(key)).isEqualTo(wantValue); + } + + public static Object[][] grpcTestCases() { + return new Object[][] { + { + "object exists", + (Act) client -> client.exists("test-uuid"), + }, + { + "insert many", + (Act) client -> client.insertMany(), + }, + { + "delete many", + (Act) client -> client.deleteMany(), + }, + }; + } + + @Name("0") + @DataMethod(source = WeaviateDataClientTest.class, method = "grpcTestCases") + @Test + public void test_collectionHandleDefaults_grpc(String __, Act act) + throws Exception { + // Arrange + var collection = CollectionDescriptor.ofMap("Things"); + var defaults = new CollectionHandleDefaults(ConsistencyLevel.ONE); + var client = new WeaviateDataClient>( + collection, null, grpc, defaults); + + // Act + act.apply(client); + + // Assert + grpc.assertNext(json -> assertJsonHasValue(json, "consistencyLevel", + WeaviateProtoBase.ConsistencyLevel.CONSISTENCY_LEVEL_ONE.toString())); + } +} 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 56e189f2e..45607c4f4 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 @@ -345,6 +345,7 @@ public void test_serialize(Object cls, Object in, String want) { } + @FunctionalInterface private interface CustomAssert extends BiConsumer { } diff --git a/src/test/java/io/weaviate/testutil/transport/MockGrpcTransport.java b/src/test/java/io/weaviate/testutil/transport/MockGrpcTransport.java new file mode 100644 index 000000000..cb504d01b --- /dev/null +++ b/src/test/java/io/weaviate/testutil/transport/MockGrpcTransport.java @@ -0,0 +1,56 @@ +package io.weaviate.testutil.transport; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.MessageOrBuilder; +import com.google.protobuf.util.JsonFormat; + +import io.weaviate.client6.v1.internal.grpc.GrpcTransport; +import io.weaviate.client6.v1.internal.grpc.Rpc; + +public class MockGrpcTransport implements GrpcTransport { + + @FunctionalInterface + public interface AssertFunction { + void apply(String json); + } + + private List requests = new ArrayList<>(); + + public void assertNext(AssertFunction... assertions) { + var assertN = Math.min(assertions.length, requests.size()); + for (var i = 0; i < assertN; i++) { + var req = requests.get(i); + String json; + try { + json = JsonFormat.printer().print(req); + } catch (InvalidProtocolBufferException e) { + throw new RuntimeException(e); + } + assertions[i].apply(json); + } + requests.clear(); + } + + @Override + public ResponseT performRequest(RequestT request, + Rpc rpc) { + requests.add((MessageOrBuilder) rpc.marshal(request)); + return null; + } + + @Override + public CompletableFuture performRequestAsync(RequestT request, + Rpc rpc) { + requests.add((MessageOrBuilder) rpc.marshal(request)); + return null; + } + + @Override + public void close() throws IOException { + } +} diff --git a/src/test/java/io/weaviate/testutil/transport/MockRestTransport.java b/src/test/java/io/weaviate/testutil/transport/MockRestTransport.java new file mode 100644 index 000000000..c3cdf1234 --- /dev/null +++ b/src/test/java/io/weaviate/testutil/transport/MockRestTransport.java @@ -0,0 +1,55 @@ +package io.weaviate.testutil.transport; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +import io.weaviate.client6.v1.internal.rest.Endpoint; +import io.weaviate.client6.v1.internal.rest.RestTransport; + +public class MockRestTransport implements RestTransport { + + private record Request(String method, String requestUrl, String body, + Map queryParameters) { + + Request(RequestT req, Endpoint ep) { + this(ep.method(req), ep.requestUrl(req), ep.body(req), ep.queryParameters(req)); + } + } + + @FunctionalInterface + public interface AssertFunction { + void apply(String method, String requestUrl, String body, Map queryParameters); + } + + private List> requests = new ArrayList<>(); + + public void assertNext(AssertFunction... assertions) { + var assertN = Math.min(assertions.length, requests.size()); + for (var i = 0; i < assertN; i++) { + var req = requests.get(i); + assertions[i].apply(req.method, req.requestUrl, req.body, req.queryParameters); + } + requests.clear(); + } + + @Override + public ResponseT performRequest(RequestT request, + Endpoint endpoint) throws IOException { + requests.add(new Request<>(request, endpoint)); + return null; + } + + @Override + public CompletableFuture performRequestAsync(RequestT request, + Endpoint endpoint) { + requests.add(new Request<>(request, endpoint)); + return null; + } + + @Override + public void close() throws IOException { + } +} From fae80887a7fb24c69ef282fbabec478e6b5958fa Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Wed, 20 Aug 2025 15:19:09 +0200 Subject: [PATCH 07/24] feat: set default consistency in all 'query' requests --- .../v1/api/collections/CollectionHandle.java | 2 +- .../collections/CollectionHandleAsync.java | 2 +- .../collections/CollectionHandleDefaults.java | 12 +- .../aggregate/AbstractAggregateClient.java | 8 +- .../aggregate/WeaviateAggregateClient.java | 8 +- .../WeaviateAggregateClientAsync.java | 8 +- .../query/AbstractQueryClient.java | 1 - .../query/WeaviateQueryClientTest.java | 126 ++++++++++++++++++ 8 files changed, 157 insertions(+), 10 deletions(-) create mode 100644 src/test/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientTest.java diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandle.java b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandle.java index c5b081e02..c4c49737c 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandle.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandle.java @@ -28,7 +28,7 @@ public CollectionHandle( CollectionDescriptor collectionDescriptor, CollectionHandleDefaults defaults) { this.config = new WeaviateConfigClient(collectionDescriptor, restTransport, grpcTransport); - this.aggregate = new WeaviateAggregateClient(collectionDescriptor, grpcTransport); + this.aggregate = new WeaviateAggregateClient(collectionDescriptor, grpcTransport, defaults); this.query = new WeaviateQueryClient<>(collectionDescriptor, grpcTransport, defaults); this.data = new WeaviateDataClient<>(collectionDescriptor, restTransport, grpcTransport, defaults); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleAsync.java b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleAsync.java index 2cd669ebf..dccc85dcd 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleAsync.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleAsync.java @@ -31,7 +31,7 @@ public CollectionHandleAsync( CollectionHandleDefaults defaults) { this.config = new WeaviateConfigClientAsync(collectionDescriptor, restTransport, grpcTransport); - this.aggregate = new WeaviateAggregateClientAsync(collectionDescriptor, grpcTransport); + this.aggregate = new WeaviateAggregateClientAsync(collectionDescriptor, grpcTransport, defaults); this.query = new WeaviateQueryClientAsync<>(collectionDescriptor, grpcTransport, defaults); this.data = new WeaviateDataClientAsync<>(collectionDescriptor, restTransport, grpcTransport, defaults); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java index 88e6c467f..5512b491d 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java @@ -14,6 +14,7 @@ import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateGrpc.WeaviateFutureStub; import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBatch; import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBatchDelete; +import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoSearchGet; import io.weaviate.client6.v1.internal.rest.Endpoint; import io.weaviate.client6.v1.internal.rest.EndpointBase; import io.weaviate.client6.v1.internal.rest.JsonEndpoint; @@ -179,19 +180,26 @@ private ConsistencyLevel consistencyLevel() { @Override public RequestM marshal(RequestT request) { var message = rpc.marshal(request); - if (message instanceof WeaviateProtoBatchDelete.BatchDeleteRequest msg) { + if (message instanceof WeaviateProtoBatch.BatchObjectsRequest msg) { var b = msg.toBuilder(); if (!msg.hasConsistencyLevel() && consistencyLevel() != null) { consistencyLevel().appendTo(b); return (RequestM) b.build(); } - } else if (message instanceof WeaviateProtoBatch.BatchObjectsRequest msg) { + } else if (message instanceof WeaviateProtoBatchDelete.BatchDeleteRequest msg) { + var b = msg.toBuilder(); + if (!msg.hasConsistencyLevel() && consistencyLevel() != null) { + consistencyLevel().appendTo(b); + return (RequestM) b.build(); + } + } else if (message instanceof WeaviateProtoSearchGet.SearchRequest msg) { var b = msg.toBuilder(); if (!msg.hasConsistencyLevel() && consistencyLevel() != null) { consistencyLevel().appendTo(b); return (RequestM) b.build(); } } + return message; } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AbstractAggregateClient.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AbstractAggregateClient.java index 4258947bd..3b557a244 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AbstractAggregateClient.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AbstractAggregateClient.java @@ -3,6 +3,7 @@ import java.util.List; import java.util.function.Function; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; import io.weaviate.client6.v1.api.collections.query.Hybrid; import io.weaviate.client6.v1.api.collections.query.NearAudio; import io.weaviate.client6.v1.api.collections.query.NearDepth; @@ -20,10 +21,15 @@ abstract class AbstractAggregateClient { protected final CollectionDescriptor collection; protected final GrpcTransport transport; + protected final CollectionHandleDefaults defaults; - AbstractAggregateClient(CollectionDescriptor collection, GrpcTransport transport) { + AbstractAggregateClient( + CollectionDescriptor collection, + GrpcTransport transport, + CollectionHandleDefaults defaults) { this.transport = transport; this.collection = collection; + this.defaults = defaults; } protected abstract ResponseT performRequest(Aggregation aggregation); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClient.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClient.java index 8f61720f4..aeb769e76 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClient.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClient.java @@ -1,12 +1,16 @@ package io.weaviate.client6.v1.api.collections.aggregate; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; import io.weaviate.client6.v1.internal.grpc.GrpcTransport; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; public class WeaviateAggregateClient extends AbstractAggregateClient { - public WeaviateAggregateClient(CollectionDescriptor collection, GrpcTransport transport) { - super(collection, transport); + public WeaviateAggregateClient( + CollectionDescriptor collection, + GrpcTransport transport, + CollectionHandleDefaults defaults) { + super(collection, transport, defaults); } protected final AggregateResponse performRequest(Aggregation aggregation) { diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClientAsync.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClientAsync.java index cdb138867..5a87cfdbc 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClientAsync.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClientAsync.java @@ -2,14 +2,18 @@ import java.util.concurrent.CompletableFuture; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; import io.weaviate.client6.v1.internal.grpc.GrpcTransport; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; public class WeaviateAggregateClientAsync extends AbstractAggregateClient, CompletableFuture> { - public WeaviateAggregateClientAsync(CollectionDescriptor collection, GrpcTransport transport) { - super(collection, transport); + public WeaviateAggregateClientAsync( + CollectionDescriptor collection, + GrpcTransport transport, + CollectionHandleDefaults defaults) { + super(collection, transport, defaults); } protected final CompletableFuture performRequest(Aggregation aggregation) { 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 589a7f685..e24fbadcb 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 @@ -13,7 +13,6 @@ abstract class AbstractQueryClient { protected final CollectionDescriptor collection; protected final GrpcTransport grpcTransport; - protected final CollectionHandleDefaults defaults; AbstractQueryClient(CollectionDescriptor collection, GrpcTransport grpcTransport, diff --git a/src/test/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientTest.java b/src/test/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientTest.java new file mode 100644 index 000000000..1145a25fc --- /dev/null +++ b/src/test/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientTest.java @@ -0,0 +1,126 @@ +package io.weaviate.client6.v1.api.collections.query; + +import java.util.Map; + +import org.assertj.core.api.Assertions; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; + +import com.google.gson.JsonParser; +import com.jparams.junit4.JParamsTestRunner; +import com.jparams.junit4.data.DataMethod; +import com.jparams.junit4.description.Name; + +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; +import io.weaviate.client6.v1.internal.ObjectBuilder; +import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBase; +import io.weaviate.client6.v1.internal.json.JSON; +import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; +import io.weaviate.testutil.transport.MockGrpcTransport; + +@RunWith(JParamsTestRunner.class) +public class WeaviateQueryClientTest { + private static MockGrpcTransport grpc; + + @BeforeClass + public static void setUp() { + grpc = new MockGrpcTransport(); + } + + @AfterClass + public static void tearDown() throws Exception { + grpc.close(); + } + + @FunctionalInterface + interface Act { + void apply(WeaviateQueryClient> client) throws Exception; + } + + private void assertJsonHasValue(String json, String key, T value) { + var gotJson = JsonParser.parseString(json).getAsJsonObject(); + Assertions.assertThat(gotJson.has(key)) + .describedAs("missing key \"%s\" in %s", key, json) + .isTrue(); + + var wantValue = JsonParser.parseString(JSON.serialize(value)); + Assertions.assertThat(gotJson.get(key)).isEqualTo(wantValue); + } + + public static Object[][] grpcTestCases() { + return new Object[][] { + { + "get by id", + (Act) client -> client.byId("test-uuid") + }, + { + "fetch objects", + (Act) client -> client.fetchObjects(ObjectBuilder.identity()), + }, + { + "bm25", + (Act) client -> client.bm25("red ballon"), + }, + { + "hybrid", + (Act) client -> client.hybrid("red ballon"), + }, + { + "nearVector", + (Act) client -> client.nearVector(new float[] {}), + }, + { + "nearText", + (Act) client -> client.nearText("weather in Arizona"), + }, + { + "nearObject", + (Act) client -> client.nearObject("test-uuid"), + }, + { + "nearImage", + (Act) client -> client.nearImage("img.jpeg"), + }, + { + "nearAudio", + (Act) client -> client.nearAudio("song.mp3"), + }, + { + "nearVideo", + (Act) client -> client.nearVideo("clip.mp4"), + }, + { + "nearDepth", + (Act) client -> client.nearDepth("20.000 leagues"), + }, + { + "nearThermal", + (Act) client -> client.nearThermal("Fahrenheit 451"), + }, + { + "nearImu", + (Act) client -> client.nearImu("6 m/s"), + }, + }; + } + + @Name("0") + @DataMethod(source = WeaviateQueryClientTest.class, method = "grpcTestCases") + @Test + public void test_collectionHandleDefaults_grpc(String __, Act act) + throws Exception { + // Arrange + var collection = CollectionDescriptor.ofMap("Things"); + var defaults = new CollectionHandleDefaults(ConsistencyLevel.ONE); + var client = new WeaviateQueryClient>(collection, grpc, defaults); + + // Act + act.apply(client); + + // Assert + grpc.assertNext(json -> assertJsonHasValue(json, "consistencyLevel", + WeaviateProtoBase.ConsistencyLevel.CONSISTENCY_LEVEL_ONE.toString())); + } +} From 1a4aa2bed02023ab3d7a09562a6586b49f2991c0 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Wed, 20 Aug 2025 16:26:30 +0200 Subject: [PATCH 08/24] chore: remove unused imports --- .../java/io/weaviate/client6/v1/api/collections/Vectorizer.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/Vectorizer.java b/src/main/java/io/weaviate/client6/v1/api/collections/Vectorizer.java index b5b6c68bb..b0cc27d2e 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/Vectorizer.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/Vectorizer.java @@ -3,7 +3,6 @@ import java.io.IOException; import java.util.EnumMap; import java.util.Map; -import java.util.function.Function; import com.google.gson.Gson; import com.google.gson.JsonObject; @@ -20,7 +19,6 @@ import io.weaviate.client6.v1.api.collections.vectorizers.NoneVectorizer; import io.weaviate.client6.v1.api.collections.vectorizers.Text2VecContextionaryVectorizer; import io.weaviate.client6.v1.api.collections.vectorizers.Text2VecWeaviateVectorizer; -import io.weaviate.client6.v1.internal.ObjectBuilder; import io.weaviate.client6.v1.internal.json.JsonEnum; public interface Vectorizer { From 423268cd7e5147b9ab4a9cfc7bfec9cc5a0d9777 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Wed, 20 Aug 2025 17:03:55 +0200 Subject: [PATCH 09/24] chore: format test cases --- .../data/WeaviateDataClientTest.java | 15 +---- .../query/WeaviateQueryClientTest.java | 65 ++++--------------- 2 files changed, 16 insertions(+), 64 deletions(-) diff --git a/src/test/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientTest.java b/src/test/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientTest.java index 0e9ae3baa..aecffae65 100644 --- a/src/test/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientTest.java +++ b/src/test/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientTest.java @@ -128,18 +128,9 @@ private void assertJsonHasValue(String json, String key, T value) { public static Object[][] grpcTestCases() { return new Object[][] { - { - "object exists", - (Act) client -> client.exists("test-uuid"), - }, - { - "insert many", - (Act) client -> client.insertMany(), - }, - { - "delete many", - (Act) client -> client.deleteMany(), - }, + { "object exists", (Act) client -> client.exists("test-uuid") }, + { "insert many", (Act) client -> client.insertMany() }, + { "delete many", (Act) client -> client.deleteMany() }, }; } diff --git a/src/test/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientTest.java b/src/test/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientTest.java index 1145a25fc..aef374385 100644 --- a/src/test/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientTest.java +++ b/src/test/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientTest.java @@ -51,58 +51,19 @@ private void assertJsonHasValue(String json, String key, T value) { public static Object[][] grpcTestCases() { return new Object[][] { - { - "get by id", - (Act) client -> client.byId("test-uuid") - }, - { - "fetch objects", - (Act) client -> client.fetchObjects(ObjectBuilder.identity()), - }, - { - "bm25", - (Act) client -> client.bm25("red ballon"), - }, - { - "hybrid", - (Act) client -> client.hybrid("red ballon"), - }, - { - "nearVector", - (Act) client -> client.nearVector(new float[] {}), - }, - { - "nearText", - (Act) client -> client.nearText("weather in Arizona"), - }, - { - "nearObject", - (Act) client -> client.nearObject("test-uuid"), - }, - { - "nearImage", - (Act) client -> client.nearImage("img.jpeg"), - }, - { - "nearAudio", - (Act) client -> client.nearAudio("song.mp3"), - }, - { - "nearVideo", - (Act) client -> client.nearVideo("clip.mp4"), - }, - { - "nearDepth", - (Act) client -> client.nearDepth("20.000 leagues"), - }, - { - "nearThermal", - (Act) client -> client.nearThermal("Fahrenheit 451"), - }, - { - "nearImu", - (Act) client -> client.nearImu("6 m/s"), - }, + { "get by id", (Act) client -> client.byId("test-uuid") }, + { "fetch objects", (Act) client -> client.fetchObjects(ObjectBuilder.identity()) }, + { "bm25", (Act) client -> client.bm25("red ballon") }, + { "hybrid", (Act) client -> client.hybrid("red ballon") }, + { "nearVector", (Act) client -> client.nearVector(new float[] {}) }, + { "nearText", (Act) client -> client.nearText("weather in Arizona") }, + { "nearObject", (Act) client -> client.nearObject("test-uuid") }, + { "nearImage", (Act) client -> client.nearImage("img.jpeg") }, + { "nearAudio", (Act) client -> client.nearAudio("song.mp3") }, + { "nearVideo", (Act) client -> client.nearVideo("clip.mp4") }, + { "nearDepth", (Act) client -> client.nearDepth("20.000 leagues") }, + { "nearThermal", (Act) client -> client.nearThermal("Fahrenheit 451") }, + { "nearImu", (Act) client -> client.nearImu("6 m/s") }, }; } From 39a60aaf2e22f63a25893b3d22a7a39ffa4bac9d Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Wed, 20 Aug 2025 17:26:13 +0200 Subject: [PATCH 10/24] refactor: add consistencyLevel via defaults::rpc utility --- .../v1/api/collections/query/QueryOperator.java | 12 ------------ .../v1/api/collections/query/QueryRequest.java | 6 +++--- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryOperator.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryOperator.java index 204c83a1e..a3844b4eb 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryOperator.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryOperator.java @@ -1,20 +1,8 @@ package io.weaviate.client6.v1.api.collections.query; -import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoSearchGet; interface QueryOperator { /** Append QueryOperator to the request message. */ void appendTo(WeaviateProtoSearchGet.SearchRequest.Builder req); - - /** - * Append QueryOperator to the request message and apply default parameters. - * Implementations generally shouldn't override this method. - */ - default void appendTo(WeaviateProtoSearchGet.SearchRequest.Builder req, CollectionHandleDefaults defaults) { - appendTo(req); - if (!req.hasConsistencyLevel() && defaults.consistencyLevel() != null) { - defaults.consistencyLevel().appendTo(req); - } - } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryRequest.java index 84d216812..9d1911286 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryRequest.java @@ -27,14 +27,14 @@ public record QueryRequest(QueryOperator operator, GroupBy groupBy) { static Rpc, WeaviateProtoSearchGet.SearchReply> rpc( CollectionDescriptor collection, CollectionHandleDefaults defaults) { - return Rpc.of( + return defaults.rpc(Rpc.of( request -> { var message = WeaviateProtoSearchGet.SearchRequest.newBuilder(); message.setUses127Api(true); message.setUses125Api(true); message.setUses123Api(true); message.setCollection(collection.name()); - request.operator.appendTo(message, defaults); + request.operator.appendTo(message); if (request.groupBy != null) { request.groupBy.appendTo(message); } @@ -50,7 +50,7 @@ static Rpc(objects); }, () -> WeaviateBlockingStub::search, - () -> WeaviateFutureStub::search); + () -> WeaviateFutureStub::search)); } static Rpc, WeaviateProtoSearchGet.SearchReply> grouped( From 939650401634a29f6d22f75214fe1439ce712279 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Wed, 20 Aug 2025 17:01:44 +0200 Subject: [PATCH 11/24] feat: add default tenant to aggregations --- .../v1/api/collections/CollectionHandle.java | 15 +++- .../collections/CollectionHandleDefaults.java | 25 +++++- .../aggregate/AggregateRequest.java | 13 +-- .../aggregate/WeaviateAggregateClient.java | 4 +- .../WeaviateAggregateClientAsync.java | 4 +- .../WeaviateAggregateClientTest.java | 84 +++++++++++++++++++ .../data/WeaviateDataClientTest.java | 10 ++- .../query/WeaviateQueryClientTest.java | 5 +- 8 files changed, 141 insertions(+), 19 deletions(-) create mode 100644 src/test/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClientTest.java diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandle.java b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandle.java index c4c49737c..87c22fb18 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandle.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandle.java @@ -79,6 +79,19 @@ public ConsistencyLevel consistencyLevel() { } public CollectionHandle withConsistencyLevel(ConsistencyLevel consistencyLevel) { - return new CollectionHandle<>(this, CollectionHandleDefaults.of(def -> def.consistencyLevel(consistencyLevel))); + return new CollectionHandle<>(this, CollectionHandleDefaults.of(with -> with.consistencyLevel(consistencyLevel))); + } + + public String tenant() { + return defaults.tenant(); + } + + public CollectionHandle withTenant(String tenant) { + return new CollectionHandle<>(this, CollectionHandleDefaults.of(with -> with.tenant(tenant))); + } + + public CollectionHandle withDefaults( + Function> fn) { + return new CollectionHandle<>(this, CollectionHandleDefaults.of(fn)); } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java index 5512b491d..9915762e5 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java @@ -12,6 +12,7 @@ import io.weaviate.client6.v1.internal.grpc.Rpc; import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateGrpc.WeaviateBlockingStub; import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateGrpc.WeaviateFutureStub; +import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoAggregate; import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBatch; import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBatchDelete; import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoSearchGet; @@ -19,7 +20,7 @@ import io.weaviate.client6.v1.internal.rest.EndpointBase; import io.weaviate.client6.v1.internal.rest.JsonEndpoint; -public record CollectionHandleDefaults(ConsistencyLevel consistencyLevel) { +public record CollectionHandleDefaults(ConsistencyLevel consistencyLevel, String tenant) { private static final String CONSISTENCY_LEVEL = "consistency_level"; /** @@ -35,18 +36,19 @@ public static CollectionHandleDefaults of(Function> none() { return ObjectBuilder.identity(); } public CollectionHandleDefaults(Builder builder) { - this(builder.consistencyLevel); + this(builder.consistencyLevel, builder.tenant); } public static final class Builder implements ObjectBuilder { private ConsistencyLevel consistencyLevel; + private String tenant; /** Set default consistency level for this collection handle. */ public Builder consistencyLevel(ConsistencyLevel consistencyLevel) { @@ -54,6 +56,12 @@ public Builder consistencyLevel(ConsistencyLevel consistencyLevel) { return this; } + /** Set default tenant for this collection handle. */ + public Builder tenant(String tenant) { + this.tenant = tenant; + return this; + } + @Override public CollectionHandleDefaults build() { return new CollectionHandleDefaults(this); @@ -176,6 +184,11 @@ private ConsistencyLevel consistencyLevel() { return CollectionHandleDefaults.this.consistencyLevel; } + /** Return tenant of the enclosing CollectionHandleDefaults object. */ + private String tenant() { + return CollectionHandleDefaults.this.tenant; + } + @SuppressWarnings("unchecked") @Override public RequestM marshal(RequestT request) { @@ -198,6 +211,12 @@ public RequestM marshal(RequestT request) { consistencyLevel().appendTo(b); return (RequestM) b.build(); } + } else if (message instanceof WeaviateProtoAggregate.AggregateRequest msg) { + var b = msg.toBuilder(); + if (msg.getTenant().isEmpty() && tenant() != null) { + b.setTenant(tenant()); + } + return (RequestM) b.build(); } return message; diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateRequest.java index 79a84505f..60a2c0700 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateRequest.java @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.Map; +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; import io.weaviate.client6.v1.internal.grpc.Rpc; import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateGrpc.WeaviateBlockingStub; import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateGrpc.WeaviateFutureStub; @@ -13,8 +14,9 @@ public record AggregateRequest(Aggregation aggregation, GroupBy groupBy) { static Rpc rpc( - CollectionDescriptor collection) { - return Rpc.of( + CollectionDescriptor collection, + CollectionHandleDefaults defaults) { + return defaults.rpc(Rpc.of( request -> { var message = WeaviateProtoAggregate.AggregateRequest.newBuilder(); message.setCollection(collection.name()); @@ -39,12 +41,13 @@ static Rpc WeaviateBlockingStub::aggregate, - () -> WeaviateFutureStub::aggregate); + () -> WeaviateFutureStub::aggregate)); } static Rpc grouped( - CollectionDescriptor collection) { - var rpc = rpc(collection); + CollectionDescriptor collection, + CollectionHandleDefaults defaults) { + var rpc = rpc(collection, defaults); return Rpc.of(request -> rpc.marshal(request), reply -> { var groups = new ArrayList>(); if (reply.hasGroupedResults()) { diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClient.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClient.java index aeb769e76..aed6d02ec 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClient.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClient.java @@ -15,11 +15,11 @@ public WeaviateAggregateClient( protected final AggregateResponse performRequest(Aggregation aggregation) { var request = new AggregateRequest(aggregation, null); - return this.transport.performRequest(request, AggregateRequest.rpc(collection)); + return this.transport.performRequest(request, AggregateRequest.rpc(collection, defaults)); } protected final AggregateResponseGrouped performRequest(Aggregation aggregation, GroupBy groupBy) { var request = new AggregateRequest(aggregation, groupBy); - return this.transport.performRequest(request, AggregateRequest.grouped(collection)); + return this.transport.performRequest(request, AggregateRequest.grouped(collection, defaults)); } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClientAsync.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClientAsync.java index 5a87cfdbc..707107861 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClientAsync.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClientAsync.java @@ -18,11 +18,11 @@ public WeaviateAggregateClientAsync( protected final CompletableFuture performRequest(Aggregation aggregation) { var request = new AggregateRequest(aggregation, null); - return this.transport.performRequestAsync(request, AggregateRequest.rpc(collection)); + return this.transport.performRequestAsync(request, AggregateRequest.rpc(collection, defaults)); } protected final CompletableFuture performRequest(Aggregation aggregation, GroupBy groupBy) { var request = new AggregateRequest(aggregation, groupBy); - return this.transport.performRequestAsync(request, AggregateRequest.grouped(collection)); + return this.transport.performRequestAsync(request, AggregateRequest.grouped(collection, defaults)); } } diff --git a/src/test/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClientTest.java b/src/test/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClientTest.java new file mode 100644 index 000000000..74e611b62 --- /dev/null +++ b/src/test/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClientTest.java @@ -0,0 +1,84 @@ +package io.weaviate.client6.v1.api.collections.aggregate; + +import org.assertj.core.api.Assertions; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; + +import com.google.gson.JsonParser; +import com.jparams.junit4.JParamsTestRunner; +import com.jparams.junit4.data.DataMethod; +import com.jparams.junit4.description.Name; + +import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; +import io.weaviate.client6.v1.api.collections.query.ConsistencyLevel; +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.testutil.transport.MockGrpcTransport; + +@RunWith(JParamsTestRunner.class) +public class WeaviateAggregateClientTest { + private static MockGrpcTransport grpc; + + @BeforeClass + public static void setUp() { + grpc = new MockGrpcTransport(); + } + + @AfterClass + public static void tearDown() throws Exception { + grpc.close(); + } + + @FunctionalInterface + interface Act { + void apply(WeaviateAggregateClient client) throws Exception; + } + + private void assertJsonHasValue(String json, String key, T value) { + var gotJson = JsonParser.parseString(json).getAsJsonObject(); + Assertions.assertThat(gotJson.has(key)) + .describedAs("missing key \"%s\" in %s", key, json) + .isTrue(); + + var wantValue = JsonParser.parseString(JSON.serialize(value)); + Assertions.assertThat(gotJson.get(key)).isEqualTo(wantValue); + } + + public static Object[][] grpcTestCases() { + return new Object[][] { + { "over all", (Act) client -> client.overAll(ObjectBuilder.identity()) }, + { "hybrid", (Act) client -> client.hybrid("red balloon", ObjectBuilder.identity()) }, + { "nearVector", (Act) client -> client.nearVector(new float[] {}, ObjectBuilder.identity()) }, + { "nearText", (Act) client -> client.nearText("red balloon", ObjectBuilder.identity()) }, + { "nearObject", (Act) client -> client.nearObject("test-uuid", ObjectBuilder.identity()) }, + { "nearImage", (Act) client -> client.nearImage("img.jpeg", ObjectBuilder.identity()) }, + { "nearAudio", (Act) client -> client.nearAudio("song.mp3", ObjectBuilder.identity()) }, + { "nearVideo", (Act) client -> client.nearVideo("clip.mp4", ObjectBuilder.identity()) }, + { "nearDepth", (Act) client -> client.nearDepth("20.000 leagues", ObjectBuilder.identity()) }, + { "nearThermal", (Act) client -> client.nearThermal("Fahrenheit 451", ObjectBuilder.identity()) }, + { "nearImu", (Act) client -> client.nearImu("6 m/s", ObjectBuilder.identity()) }, + }; + } + + @Name("{0}") + @DataMethod(source = WeaviateAggregateClientTest.class, method = "grpcTestCases") + @Test + public void test_collectionHandleDefaults_grpc(String __, Act act) + throws Exception { + // Arrange + var collection = CollectionDescriptor.ofMap("Things"); + var defaults = CollectionHandleDefaults.of(d -> d + .consistencyLevel(ConsistencyLevel.ONE) + .tenant("john_doe")); + var client = new WeaviateAggregateClient(collection, grpc, defaults); + + // Act + act.apply(client); + + // Assert + grpc.assertNext(json -> assertJsonHasValue(json, "tenant", "john_doe")); + } +} diff --git a/src/test/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientTest.java b/src/test/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientTest.java index aecffae65..6fdaab947 100644 --- a/src/test/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientTest.java +++ b/src/test/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientTest.java @@ -90,14 +90,15 @@ public static Object[][] restTestCases() { }; } - @Name("0") + @Name("{0}") @DataMethod(source = WeaviateDataClientTest.class, method = "restTestCases") @Test public void test_collectionHandleDefaults_rest(String __, ConsistencyLevel cl, Location clLoc, Act act) throws Exception { // Arrange var collection = CollectionDescriptor.ofMap("Things"); - var defaults = new CollectionHandleDefaults(cl); + var defaults = CollectionHandleDefaults.of(d -> d + .consistencyLevel(cl)); var client = new WeaviateDataClient>( collection, rest, null, defaults); @@ -134,14 +135,15 @@ public static Object[][] grpcTestCases() { }; } - @Name("0") + @Name("{0}") @DataMethod(source = WeaviateDataClientTest.class, method = "grpcTestCases") @Test public void test_collectionHandleDefaults_grpc(String __, Act act) throws Exception { // Arrange var collection = CollectionDescriptor.ofMap("Things"); - var defaults = new CollectionHandleDefaults(ConsistencyLevel.ONE); + var defaults = CollectionHandleDefaults.of(d -> d + .consistencyLevel(ConsistencyLevel.ONE)); var client = new WeaviateDataClient>( collection, null, grpc, defaults); diff --git a/src/test/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientTest.java b/src/test/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientTest.java index aef374385..90d4f9eb2 100644 --- a/src/test/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientTest.java +++ b/src/test/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientTest.java @@ -67,14 +67,15 @@ public static Object[][] grpcTestCases() { }; } - @Name("0") + @Name("{0}") @DataMethod(source = WeaviateQueryClientTest.class, method = "grpcTestCases") @Test public void test_collectionHandleDefaults_grpc(String __, Act act) throws Exception { // Arrange var collection = CollectionDescriptor.ofMap("Things"); - var defaults = new CollectionHandleDefaults(ConsistencyLevel.ONE); + var defaults = CollectionHandleDefaults.of(d -> d + .consistencyLevel(ConsistencyLevel.ONE)); var client = new WeaviateQueryClient>(collection, grpc, defaults); // Act From 0e8b422e5afde887d4cdba323cd27fe501dc142d Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Wed, 20 Aug 2025 17:27:50 +0200 Subject: [PATCH 12/24] feat: add default tenant to queries --- .../v1/api/collections/CollectionHandleDefaults.java | 5 ++++- .../client6/v1/api/collections/query/QueryRequest.java | 6 +++--- .../api/collections/query/WeaviateQueryClientTest.java | 10 +++++++--- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java index 9915762e5..99551bb51 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java @@ -209,8 +209,11 @@ public RequestM marshal(RequestT request) { var b = msg.toBuilder(); if (!msg.hasConsistencyLevel() && consistencyLevel() != null) { consistencyLevel().appendTo(b); - return (RequestM) b.build(); } + if (msg.getTenant().isEmpty() && tenant() != null) { + b.setTenant(tenant()); + } + return (RequestM) b.build(); } else if (message instanceof WeaviateProtoAggregate.AggregateRequest msg) { var b = msg.toBuilder(); if (msg.getTenant().isEmpty() && tenant() != null) { diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryRequest.java index 9d1911286..2d59e9aa6 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryRequest.java @@ -88,8 +88,8 @@ static Rpc WeaviateObject unmarshalResultObject( WeaviateProtoSearchGet.PropertiesResult propertiesResult, WeaviateProtoSearchGet.MetadataResult metadataResult, - CollectionDescriptor descriptor) { - var object = unmarshalWithReferences(propertiesResult, metadataResult, descriptor); + CollectionDescriptor collection) { + var object = unmarshalWithReferences(propertiesResult, metadataResult, collection); var metadata = new QueryMetadata.Builder() .uuid(object.metadata().uuid()) .vectors(object.metadata().vectors()); @@ -112,7 +112,7 @@ private static WeaviateObject unmarshalResultObjec if (metadataResult.getExplainScorePresent()) { metadata.explainScore(metadataResult.getExplainScore()); } - return new WeaviateObject<>(descriptor.name(), object.properties(), object.references(), metadata.build()); + return new WeaviateObject<>(collection.name(), object.properties(), object.references(), metadata.build()); } private static WeaviateObject unmarshalWithReferences( diff --git a/src/test/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientTest.java b/src/test/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientTest.java index 90d4f9eb2..38ce03b74 100644 --- a/src/test/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientTest.java +++ b/src/test/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientTest.java @@ -75,14 +75,18 @@ public void test_collectionHandleDefaults_grpc(String __, Act act) // Arrange var collection = CollectionDescriptor.ofMap("Things"); var defaults = CollectionHandleDefaults.of(d -> d - .consistencyLevel(ConsistencyLevel.ONE)); + .consistencyLevel(ConsistencyLevel.ONE) + .tenant("john_doe")); var client = new WeaviateQueryClient>(collection, grpc, defaults); // Act act.apply(client); // Assert - grpc.assertNext(json -> assertJsonHasValue(json, "consistencyLevel", - WeaviateProtoBase.ConsistencyLevel.CONSISTENCY_LEVEL_ONE.toString())); + grpc.assertNext(json -> { + assertJsonHasValue(json, "tenant", "john_doe"); + assertJsonHasValue(json, "consistencyLevel", + WeaviateProtoBase.ConsistencyLevel.CONSISTENCY_LEVEL_ONE.toString()); + }); } } From e197cdef28cb0bff1a5fe85dfc1ba63501bd7837 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Wed, 20 Aug 2025 19:58:16 +0200 Subject: [PATCH 13/24] feat: add default tenant to 'data' operations --- .../collections/CollectionHandleDefaults.java | 45 +++++- .../v1/api/collections/WeaviateObject.java | 2 +- .../collections/data/DeleteObjectRequest.java | 3 +- .../collections/data/InsertObjectRequest.java | 6 +- .../data/ReferenceAddManyRequest.java | 3 +- .../collections/data/ReferenceAddRequest.java | 3 +- .../data/ReferenceDeleteRequest.java | 3 +- .../data/ReferenceReplaceRequest.java | 3 +- .../data/ReplaceObjectRequest.java | 8 +- .../collections/data/UpdateObjectRequest.java | 8 +- .../collections/data/WriteWeaviateObject.java | 129 ++++++++++++++++++ .../client6/v1/internal/json/JSON.java | 2 + .../data/WeaviateDataClientTest.java | 60 ++++++-- .../testutil/transport/MockGrpcTransport.java | 24 ++-- .../testutil/transport/MockRestTransport.java | 11 +- 15 files changed, 270 insertions(+), 40 deletions(-) create mode 100644 src/main/java/io/weaviate/client6/v1/api/collections/data/WriteWeaviateObject.java diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java index 99551bb51..028042c04 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java @@ -22,6 +22,7 @@ public record CollectionHandleDefaults(ConsistencyLevel consistencyLevel, String tenant) { private static final String CONSISTENCY_LEVEL = "consistency_level"; + private static final String TENANT = "tenant"; /** * Set default values for query / aggregation requests. @@ -93,12 +94,17 @@ public static interface WithDefaults> { ConsistencyLevel consistencyLevel(); SelfT withConsistencyLevel(ConsistencyLevel consistencyLevel); + + String tenant(); + + SelfT withTenant(String tenant); } private class ContextEndpoint extends EndpointBase implements JsonEndpoint { private final Location consistencyLevelLoc; + private final Location tenantLoc; private final Endpoint endpoint; ContextEndpoint(EndpointBuilder builder) { @@ -107,6 +113,7 @@ private class ContextEndpoint extends EndpointBase queryParameters(RequestT request) { // Copy the map, as it's most likely unmodifiable. var query = new HashMap<>(super.queryParameters(request)); - if (consistencyLevel() != null && consistencyLevelLoc == Location.QUERY) { + if (consistencyLevel() != null && consistencyLevelLoc != null && consistencyLevelLoc == Location.QUERY) { query.putIfAbsent(CONSISTENCY_LEVEL, consistencyLevel()); } + if (tenant() != null && tenantLoc != null && tenantLoc == Location.QUERY) { + query.putIfAbsent(TENANT, tenant()); + } return query; } @@ -129,9 +139,12 @@ public Map queryParameters(RequestT request) { @Override public String body(RequestT request) { if (request instanceof WithDefaults wd) { - if (wd.consistencyLevel() == null) { + if (wd.consistencyLevel() == null && consistencyLevel() != null) { wd = wd.withConsistencyLevel(consistencyLevel()); } + if (wd.tenant() == null && tenant() != null) { + wd = wd.withTenant(tenant()); + } // This cast is safe as long as `wd` returns its own type, // which it does as per the interface contract. request = (RequestT) wd; @@ -153,6 +166,7 @@ public class EndpointBuilder implements ObjectBuilder endpoint; private Location consistencyLevelLoc; + private Location tenantLoc; EndpointBuilder(Endpoint ep) { this.endpoint = ep; @@ -164,6 +178,12 @@ public EndpointBuilder consistencyLevel(Location loc) { return this; } + /** Control which part of the request to add default consistency level to. */ + public EndpointBuilder tenant(Location loc) { + this.tenantLoc = loc; + return this; + } + @Override public Endpoint build() { return new ContextEndpoint<>(this); @@ -197,14 +217,30 @@ public RequestM marshal(RequestT request) { var b = msg.toBuilder(); if (!msg.hasConsistencyLevel() && consistencyLevel() != null) { consistencyLevel().appendTo(b); - return (RequestM) b.build(); } + + // Tenant must be applied to each batch object individually. + msg.getObjectsList().stream() + .map(obj -> { + var objBuilder = obj.toBuilder(); + if (obj.getTenant().isEmpty() && tenant() != null) { + objBuilder.setTenant(tenant()); + } + return objBuilder.build(); + }) + .forEach(b::addObjects); + return (RequestM) b.build(); + } else if (message instanceof WeaviateProtoBatchDelete.BatchDeleteRequest msg) { var b = msg.toBuilder(); if (!msg.hasConsistencyLevel() && consistencyLevel() != null) { consistencyLevel().appendTo(b); - return (RequestM) b.build(); } + if (msg.getTenant().isEmpty() && tenant() != null) { + b.setTenant(tenant()); + } + return (RequestM) b.build(); + } else if (message instanceof WeaviateProtoSearchGet.SearchRequest msg) { var b = msg.toBuilder(); if (!msg.hasConsistencyLevel() && consistencyLevel() != null) { @@ -214,6 +250,7 @@ public RequestM marshal(RequestT request) { b.setTenant(tenant()); } return (RequestM) b.build(); + } else if (message instanceof WeaviateProtoAggregate.AggregateRequest msg) { var b = msg.toBuilder(); if (msg.getTenant().isEmpty() && tenant() != null) { 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 7b1b40306..c96b22916 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 @@ -187,7 +187,7 @@ public void write(JsonWriter out, WeaviateObject value) throws IOExcept return builder.build(); } - }; + }.nullSafe(); } } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteObjectRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteObjectRequest.java index ecb2adb2d..01efdb8fe 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteObjectRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteObjectRequest.java @@ -19,6 +19,7 @@ public static final Endpoint endpoint( request -> "/objects/" + collection.name() + "/" + request.uuid, request -> Collections.emptyMap()), add -> add - .consistencyLevel(Location.QUERY)); + .consistencyLevel(Location.QUERY) + .tenant(Location.QUERY)); } } 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 97fecddc8..311ee462d 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 @@ -27,8 +27,10 @@ public static final Endpoint, WeaviateObject "POST", request -> "/objects/", request -> Collections.emptyMap(), - request -> JSON.serialize(request.object, TypeToken.getParameterized( - WeaviateObject.class, collection.typeToken().getType(), Reference.class, ObjectMetadata.class)), + request -> 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))), diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceAddManyRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceAddManyRequest.java index 72b673bba..1ca2591f8 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceAddManyRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceAddManyRequest.java @@ -34,7 +34,8 @@ public static final Endpoint return new ReferenceAddManyResponse(errors); }), add -> add - .consistencyLevel(Location.QUERY)); + .consistencyLevel(Location.QUERY) + .tenant(Location.QUERY)); } } 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 5fea35c24..cb608e460 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 @@ -21,7 +21,8 @@ public static final Endpoint endpoint( request -> Collections.emptyMap(), request -> JSON.serialize(request.reference)), add -> add - .consistencyLevel(Location.QUERY)); + .consistencyLevel(Location.QUERY) + .tenant(Location.QUERY)); } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceDeleteRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceDeleteRequest.java index 5038e0812..f9bb17ebc 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceDeleteRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceDeleteRequest.java @@ -21,6 +21,7 @@ public static final Endpoint endpoint( request -> Collections.emptyMap(), request -> JSON.serialize(request.reference)), add -> add - .consistencyLevel(Location.QUERY)); + .consistencyLevel(Location.QUERY) + .tenant(Location.QUERY)); } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceReplaceRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceReplaceRequest.java index 8d8aaf1e2..2faf1cb6a 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceReplaceRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceReplaceRequest.java @@ -22,6 +22,7 @@ public static final Endpoint endpoint( request -> Collections.emptyMap(), request -> JSON.serialize(List.of(request.reference))), add -> add - .consistencyLevel(Location.QUERY)); + .consistencyLevel(Location.QUERY) + .tenant(Location.QUERY)); } } 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 1ecb5455c..19ca5386f 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 @@ -25,10 +25,12 @@ static final Endpoint, Void> endpoint(CollectionDesc request -> "PUT", request -> "/objects/" + collection.name() + "/" + request.object.metadata().uuid(), request -> Collections.emptyMap(), - request -> JSON.serialize(request.object, TypeToken.getParameterized( - WeaviateObject.class, collection.typeToken().getType(), Reference.class, ObjectMetadata.class))), + request -> JSON.serialize( + new WriteWeaviateObject<>(request.object, defaults.tenant()), + TypeToken.getParameterized(WriteWeaviateObject.class, collection.typeToken().getType()))), add -> add - .consistencyLevel(Location.QUERY)); + .consistencyLevel(Location.QUERY) + .tenant(Location.BODY)); } public static ReplaceObjectRequest of(String collectionName, String uuid, 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 28423c752..ada6c47b6 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 @@ -25,10 +25,12 @@ static final Endpoint, Void> endpoint(CollectionDescr request -> "PATCH", request -> "/objects/" + collection.name() + "/" + request.object.metadata().uuid(), request -> Collections.emptyMap(), - request -> JSON.serialize(request.object, TypeToken.getParameterized( - WeaviateObject.class, collection.typeToken().getType(), Reference.class, ObjectMetadata.class))), + request -> JSON.serialize( + new WriteWeaviateObject<>(request.object, defaults.tenant()), + TypeToken.getParameterized(WriteWeaviateObject.class, collection.typeToken().getType()))), add -> add - .consistencyLevel(Location.QUERY)); + .consistencyLevel(Location.QUERY) + .tenant(Location.BODY)); } public static UpdateObjectRequest of(String collectionName, String uuid, 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 new file mode 100644 index 000000000..a351e6667 --- /dev/null +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/WriteWeaviateObject.java @@ -0,0 +1,129 @@ +package io.weaviate.client6.v1.api.collections.data; + +import java.io.IOException; +import java.lang.reflect.ParameterizedType; +import java.util.List; +import java.util.Map; + +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.api.collections.ObjectMetadata; +import io.weaviate.client6.v1.api.collections.WeaviateObject; + +public record WriteWeaviateObject

( + String collection, + P properties, + Map> references, + ObjectMetadata metadata, + String tenant) { + + WriteWeaviateObject(WeaviateObject object, String tenant) { + this(object.collection(), object.properties(), object.references(), object.metadata(), tenant); + } + + 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 != WriteWeaviateObject.class || + !(type instanceof ParameterizedType parameterized) + || parameterized.getActualTypeArguments().length < 1) { + return null; + } + + var typeParams = parameterized.getActualTypeArguments(); + final var propertiesType = typeParams[0]; + + 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(); + + 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 : refEntry.getValue()) { + var beacon = referencesAdapter.toJsonTree(reference); + beacons.add(beacon); + } + 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(); + } + + @Override + public WriteWeaviateObject 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 = referencesAdapter.fromJsonTree(el); + builder.reference(property.getKey(), (Reference) beacon); + } + } + } + + builder.properties(propertiesAdapter.fromJsonTree(trueProperties)); + + metadata.uuid(object.get("id").getAsString()); + builder.metadata(metadata.build()); + + var tenant = object.get("tenant"); + return new WriteWeaviateObject<>(builder.build(), tenant != null ? tenant.getAsString() : ""); + } + }.nullSafe(); + } + } +} 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 ca52d4c2d..960d40279 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 @@ -13,6 +13,8 @@ public final class JSON { // TypeAdapterFactories --------------------------------------------------- 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( io.weaviate.client6.v1.api.collections.CollectionConfig.CustomTypeAdapterFactory.INSTANCE); gsonBuilder.registerTypeAdapterFactory( diff --git a/src/test/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientTest.java b/src/test/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientTest.java index 6fdaab947..c7c229dbf 100644 --- a/src/test/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientTest.java +++ b/src/test/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientTest.java @@ -50,41 +50,49 @@ public static Object[][] restTestCases() { { "insert single object", ConsistencyLevel.ONE, Location.QUERY, + "john_doe", Location.BODY, (Act) client -> client.insert(Map.of()), }, { "replace single object", ConsistencyLevel.ONE, Location.QUERY, + "john_doe", Location.BODY, (Act) client -> client.replace("test-uuid", ObjectBuilder.identity()), }, { "update single object", ConsistencyLevel.ONE, Location.QUERY, + "john_doe", Location.BODY, (Act) client -> client.update("test-uuid", ObjectBuilder.identity()), }, { "delete by id", ConsistencyLevel.ONE, Location.QUERY, + "john_doe", Location.QUERY, (Act) client -> client.delete("test-uuid"), }, { "add reference", ConsistencyLevel.ONE, Location.QUERY, + "john_doe", Location.QUERY, (Act) client -> client.referenceAdd("from-uuid", "from_property", Reference.uuids("to-uuid")), }, { "add reference many", ConsistencyLevel.ONE, Location.QUERY, + "john_doe", Location.QUERY, (Act) client -> client.referenceAddMany(), }, { "replace reference", ConsistencyLevel.ONE, Location.QUERY, + "john_doe", Location.QUERY, (Act) client -> client.referenceReplace("from-uuid", "from_property", Reference.uuids("to-uuid")), }, { "delete reference", ConsistencyLevel.ONE, Location.QUERY, + "john_doe", Location.QUERY, (Act) client -> client.referenceDelete("from-uuid", "from_property", Reference.uuids("to-uuid")), }, }; @@ -93,12 +101,16 @@ public static Object[][] restTestCases() { @Name("{0}") @DataMethod(source = WeaviateDataClientTest.class, method = "restTestCases") @Test - public void test_collectionHandleDefaults_rest(String __, ConsistencyLevel cl, Location clLoc, Act act) + public void test_collectionHandleDefaults_rest(String __, + ConsistencyLevel cl, Location clLoc, + String tenant, Location tenantLoc, + Act act) throws Exception { // Arrange var collection = CollectionDescriptor.ofMap("Things"); var defaults = CollectionHandleDefaults.of(d -> d - .consistencyLevel(cl)); + .consistencyLevel(cl) + .tenant(tenant)); var client = new WeaviateDataClient>( collection, rest, null, defaults); @@ -114,6 +126,14 @@ public void test_collectionHandleDefaults_rest(String __, ConsistencyLevel cl, L case BODY: assertJsonHasValue(body, "consistency_level", defaults.consistencyLevel()); } + + switch (tenantLoc) { + case QUERY: + Assertions.assertThat(query).containsEntry("tenant", defaults.tenant()); + break; + case BODY: + assertJsonHasValue(body, "tenant", defaults.tenant()); + } }); } @@ -130,7 +150,6 @@ private void assertJsonHasValue(String json, String key, T value) { public static Object[][] grpcTestCases() { return new Object[][] { { "object exists", (Act) client -> client.exists("test-uuid") }, - { "insert many", (Act) client -> client.insertMany() }, { "delete many", (Act) client -> client.deleteMany() }, }; } @@ -138,12 +157,12 @@ public static Object[][] grpcTestCases() { @Name("{0}") @DataMethod(source = WeaviateDataClientTest.class, method = "grpcTestCases") @Test - public void test_collectionHandleDefaults_grpc(String __, Act act) - throws Exception { + public void test_collectionHandleDefaults_grpc(String __, Act act) throws Exception { // Arrange var collection = CollectionDescriptor.ofMap("Things"); var defaults = CollectionHandleDefaults.of(d -> d - .consistencyLevel(ConsistencyLevel.ONE)); + .consistencyLevel(ConsistencyLevel.ONE) + .tenant("john_doe")); var client = new WeaviateDataClient>( collection, null, grpc, defaults); @@ -151,7 +170,32 @@ public void test_collectionHandleDefaults_grpc(String __, Act act) act.apply(client); // Assert - grpc.assertNext(json -> assertJsonHasValue(json, "consistencyLevel", - WeaviateProtoBase.ConsistencyLevel.CONSISTENCY_LEVEL_ONE.toString())); + grpc.assertNext(json -> { + assertJsonHasValue(json, "tenant", "john_doe"); + assertJsonHasValue(json, "consistencyLevel", + WeaviateProtoBase.ConsistencyLevel.CONSISTENCY_LEVEL_ONE.toString()); + }); + } + + @Test + public void test_defaultTenant_insertMany() { + // Arrange + var collection = CollectionDescriptor.ofMap("Things"); + var defaults = CollectionHandleDefaults.of(d -> d + .consistencyLevel(ConsistencyLevel.ONE) + .tenant("john_doe")); + var client = new WeaviateDataClient>( + collection, null, grpc, defaults); + + // Act + client.insertMany(Map.of()); + + // Assert + grpc.assertNext(json -> { + // Tenant is nested in each of the batch objects + Assertions.assertThat(json).containsSequence("\"tenant\": \"john_doe\""); + assertJsonHasValue(json, "consistencyLevel", + WeaviateProtoBase.ConsistencyLevel.CONSISTENCY_LEVEL_ONE.toString()); + }); } } diff --git a/src/test/java/io/weaviate/testutil/transport/MockGrpcTransport.java b/src/test/java/io/weaviate/testutil/transport/MockGrpcTransport.java index cb504d01b..ebea2fea7 100644 --- a/src/test/java/io/weaviate/testutil/transport/MockGrpcTransport.java +++ b/src/test/java/io/weaviate/testutil/transport/MockGrpcTransport.java @@ -23,23 +23,27 @@ public interface AssertFunction { public void assertNext(AssertFunction... assertions) { var assertN = Math.min(assertions.length, requests.size()); - for (var i = 0; i < assertN; i++) { - var req = requests.get(i); - String json; - try { - json = JsonFormat.printer().print(req); - } catch (InvalidProtocolBufferException e) { - throw new RuntimeException(e); + try { + for (var i = 0; i < assertN; i++) { + var req = requests.get(i); + String json; + try { + json = JsonFormat.printer().print(req); + } catch (InvalidProtocolBufferException e) { + throw new RuntimeException(e); + } + assertions[i].apply(json); } - assertions[i].apply(json); + } finally { + requests.clear(); } - requests.clear(); } @Override public ResponseT performRequest(RequestT request, Rpc rpc) { - requests.add((MessageOrBuilder) rpc.marshal(request)); + var r = rpc.marshal(request); + requests.add((MessageOrBuilder) r); return null; } diff --git a/src/test/java/io/weaviate/testutil/transport/MockRestTransport.java b/src/test/java/io/weaviate/testutil/transport/MockRestTransport.java index c3cdf1234..1ae6c4498 100644 --- a/src/test/java/io/weaviate/testutil/transport/MockRestTransport.java +++ b/src/test/java/io/weaviate/testutil/transport/MockRestTransport.java @@ -28,11 +28,14 @@ public interface AssertFunction { public void assertNext(AssertFunction... assertions) { var assertN = Math.min(assertions.length, requests.size()); - for (var i = 0; i < assertN; i++) { - var req = requests.get(i); - assertions[i].apply(req.method, req.requestUrl, req.body, req.queryParameters); + try { + for (var i = 0; i < assertN; i++) { + var req = requests.get(i); + assertions[i].apply(req.method, req.requestUrl, req.body, req.queryParameters); + } + } finally { + requests.clear(); } - requests.clear(); } @Override From b1a15f31bca8988f2485d1e5fcbd0131d1271808 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Thu, 21 Aug 2025 23:05:09 +0200 Subject: [PATCH 14/24] refactor: simplify the logic for adding default request parameters Enpoint interface already provides a convenient way to supply query parameters, so there isn't much value in indirecting this over ContextEndpoint. Furthermore, the latter's implementation assumes too much knowledge of the internal.rest package. As for gRPC, ContextRpc had to do type checks, so there's hardly any code savings that this approach brings. Adding the parameters to the messages 'in place' seems to me much more straightforward. Finally, I merged the 3 test classes for data/query/aggregate namespaces into one because they follow the same structure, so grouping them will benefit the reader. --- .../v1/api/collections/CollectionHandle.java | 10 +- .../collections/CollectionHandleDefaults.java | 227 +----------------- .../aggregate/AggregateRequest.java | 7 +- .../collections/data/DeleteManyRequest.java | 80 +++--- .../collections/data/DeleteObjectRequest.java | 15 +- .../collections/data/InsertManyRequest.java | 101 ++++---- .../collections/data/InsertObjectRequest.java | 29 ++- .../data/ReferenceAddManyRequest.java | 38 ++- .../collections/data/ReferenceAddRequest.java | 19 +- .../data/ReferenceDeleteRequest.java | 17 +- .../data/ReferenceReplaceRequest.java | 16 +- .../data/ReplaceObjectRequest.java | 22 +- .../collections/data/UpdateObjectRequest.java | 22 +- .../api/collections/query/QueryRequest.java | 12 +- ...entTest.java => CollectionHandleTest.java} | 123 ++++++---- .../WeaviateAggregateClientTest.java | 84 ------- .../query/WeaviateQueryClientTest.java | 92 ------- 17 files changed, 277 insertions(+), 637 deletions(-) rename src/test/java/io/weaviate/client6/v1/api/collections/{data/WeaviateDataClientTest.java => CollectionHandleTest.java} (50%) delete mode 100644 src/test/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClientTest.java delete mode 100644 src/test/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientTest.java diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandle.java b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandle.java index 87c22fb18..26ccf67c5 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandle.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandle.java @@ -25,12 +25,12 @@ public class CollectionHandle { public CollectionHandle( RestTransport restTransport, GrpcTransport grpcTransport, - CollectionDescriptor collectionDescriptor, + CollectionDescriptor collection, CollectionHandleDefaults defaults) { - this.config = new WeaviateConfigClient(collectionDescriptor, restTransport, grpcTransport); - this.aggregate = new WeaviateAggregateClient(collectionDescriptor, grpcTransport, defaults); - this.query = new WeaviateQueryClient<>(collectionDescriptor, grpcTransport, defaults); - this.data = new WeaviateDataClient<>(collectionDescriptor, restTransport, grpcTransport, defaults); + this.config = new WeaviateConfigClient(collection, restTransport, grpcTransport); + this.aggregate = new WeaviateAggregateClient(collection, grpcTransport, defaults); + this.query = new WeaviateQueryClient<>(collection, grpcTransport, defaults); + this.data = new WeaviateDataClient<>(collection, restTransport, grpcTransport, defaults); this.defaults = defaults; } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java index 028042c04..b74447f6e 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java @@ -1,24 +1,12 @@ package io.weaviate.client6.v1.api.collections; +import java.util.Collections; import java.util.HashMap; import java.util.Map; -import java.util.function.BiFunction; import java.util.function.Function; -import com.google.common.util.concurrent.ListenableFuture; - import io.weaviate.client6.v1.api.collections.query.ConsistencyLevel; import io.weaviate.client6.v1.internal.ObjectBuilder; -import io.weaviate.client6.v1.internal.grpc.Rpc; -import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateGrpc.WeaviateBlockingStub; -import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateGrpc.WeaviateFutureStub; -import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoAggregate; -import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBatch; -import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBatchDelete; -import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoSearchGet; -import io.weaviate.client6.v1.internal.rest.Endpoint; -import io.weaviate.client6.v1.internal.rest.EndpointBase; -import io.weaviate.client6.v1.internal.rest.JsonEndpoint; public record CollectionHandleDefaults(ConsistencyLevel consistencyLevel, String tenant) { private static final String CONSISTENCY_LEVEL = "consistency_level"; @@ -69,212 +57,17 @@ public CollectionHandleDefaults build() { } } - public Endpoint endpoint(Endpoint ep, - Function, ObjectBuilder>> fn) { - return fn.apply(new EndpointBuilder<>(ep)).build(); - } - - public Rpc rpc( - Rpc rpc) { - return new ContextRpc<>(rpc); - } - - /** Which part of the request a parameter should be added to. */ - public static enum Location { - /** Query string. */ - QUERY, - /** - * Request body. {@code RequestT} must implement {@link WithDefaults} for the - * changes to be applied. - */ - BODY; - } - - public static interface WithDefaults> { - ConsistencyLevel consistencyLevel(); - - SelfT withConsistencyLevel(ConsistencyLevel consistencyLevel); - - String tenant(); - - SelfT withTenant(String tenant); - } - - private class ContextEndpoint extends EndpointBase - implements JsonEndpoint { - - private final Location consistencyLevelLoc; - private final Location tenantLoc; - private final Endpoint endpoint; - - ContextEndpoint(EndpointBuilder builder) { - super(builder.endpoint::method, - builder.endpoint::requestUrl, - builder.endpoint::queryParameters, - builder.endpoint::body); - this.consistencyLevelLoc = builder.consistencyLevelLoc; - this.tenantLoc = builder.tenantLoc; - this.endpoint = builder.endpoint; + public Map queryParameters() { + if (consistencyLevel == null && tenant == null) { + return Collections.emptyMap(); } - - /** Return consistencyLevel of the enclosing CollectionHandleDefaults object. */ - private ConsistencyLevel consistencyLevel() { - return CollectionHandleDefaults.this.consistencyLevel; + var query = new HashMap(); + if (consistencyLevel != null) { + query.put("consistency_level", consistencyLevel); } - - @Override - public Map queryParameters(RequestT request) { - // Copy the map, as it's most likely unmodifiable. - var query = new HashMap<>(super.queryParameters(request)); - if (consistencyLevel() != null && consistencyLevelLoc != null && consistencyLevelLoc == Location.QUERY) { - query.putIfAbsent(CONSISTENCY_LEVEL, consistencyLevel()); - } - if (tenant() != null && tenantLoc != null && tenantLoc == Location.QUERY) { - query.putIfAbsent(TENANT, tenant()); - } - return query; - } - - @SuppressWarnings("unchecked") - @Override - public String body(RequestT request) { - if (request instanceof WithDefaults wd) { - if (wd.consistencyLevel() == null && consistencyLevel() != null) { - wd = wd.withConsistencyLevel(consistencyLevel()); - } - if (wd.tenant() == null && tenant() != null) { - wd = wd.withTenant(tenant()); - } - // This cast is safe as long as `wd` returns its own type, - // which it does as per the interface contract. - request = (RequestT) wd; - } - return super.body(request); - } - - @Override - public ResponseT deserializeResponse(int statusCode, String responseBody) { - return EndpointBase.deserializeResponse(endpoint, statusCode, responseBody); - } - } - - /** - * EndpointBuilder configures how CollectionHandleDefautls - * are added to a REST request. - */ - public class EndpointBuilder implements ObjectBuilder> { - private final Endpoint endpoint; - - private Location consistencyLevelLoc; - private Location tenantLoc; - - EndpointBuilder(Endpoint ep) { - this.endpoint = ep; - } - - /** Control which part of the request to add default consistency level to. */ - public EndpointBuilder consistencyLevel(Location loc) { - this.consistencyLevelLoc = loc; - return this; - } - - /** Control which part of the request to add default consistency level to. */ - public EndpointBuilder tenant(Location loc) { - this.tenantLoc = loc; - return this; - } - - @Override - public Endpoint build() { - return new ContextEndpoint<>(this); - } - } - - private class ContextRpc - implements Rpc { - - private final Rpc rpc; - - ContextRpc(Rpc rpc) { - this.rpc = rpc; - } - - /** Return consistencyLevel of the enclosing CollectionHandleDefaults object. */ - private ConsistencyLevel consistencyLevel() { - return CollectionHandleDefaults.this.consistencyLevel; - } - - /** Return tenant of the enclosing CollectionHandleDefaults object. */ - private String tenant() { - return CollectionHandleDefaults.this.tenant; - } - - @SuppressWarnings("unchecked") - @Override - public RequestM marshal(RequestT request) { - var message = rpc.marshal(request); - if (message instanceof WeaviateProtoBatch.BatchObjectsRequest msg) { - var b = msg.toBuilder(); - if (!msg.hasConsistencyLevel() && consistencyLevel() != null) { - consistencyLevel().appendTo(b); - } - - // Tenant must be applied to each batch object individually. - msg.getObjectsList().stream() - .map(obj -> { - var objBuilder = obj.toBuilder(); - if (obj.getTenant().isEmpty() && tenant() != null) { - objBuilder.setTenant(tenant()); - } - return objBuilder.build(); - }) - .forEach(b::addObjects); - return (RequestM) b.build(); - - } else if (message instanceof WeaviateProtoBatchDelete.BatchDeleteRequest msg) { - var b = msg.toBuilder(); - if (!msg.hasConsistencyLevel() && consistencyLevel() != null) { - consistencyLevel().appendTo(b); - } - if (msg.getTenant().isEmpty() && tenant() != null) { - b.setTenant(tenant()); - } - return (RequestM) b.build(); - - } else if (message instanceof WeaviateProtoSearchGet.SearchRequest msg) { - var b = msg.toBuilder(); - if (!msg.hasConsistencyLevel() && consistencyLevel() != null) { - consistencyLevel().appendTo(b); - } - if (msg.getTenant().isEmpty() && tenant() != null) { - b.setTenant(tenant()); - } - return (RequestM) b.build(); - - } else if (message instanceof WeaviateProtoAggregate.AggregateRequest msg) { - var b = msg.toBuilder(); - if (msg.getTenant().isEmpty() && tenant() != null) { - b.setTenant(tenant()); - } - return (RequestM) b.build(); - } - - return message; - } - - @Override - public ResponseT unmarshal(ReplyM reply) { - return rpc.unmarshal(reply); - } - - @Override - public BiFunction method() { - return rpc.method(); - } - - @Override - public BiFunction> methodAsync() { - return rpc.methodAsync(); + if (tenant != null) { + query.put("tenant", tenant); } + return query; } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateRequest.java index 60a2c0700..c20ab920e 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateRequest.java @@ -16,7 +16,7 @@ public record AggregateRequest(Aggregation aggregation, GroupBy groupBy) { static Rpc rpc( CollectionDescriptor collection, CollectionHandleDefaults defaults) { - return defaults.rpc(Rpc.of( + return Rpc.of( request -> { var message = WeaviateProtoAggregate.AggregateRequest.newBuilder(); message.setCollection(collection.name()); @@ -24,6 +24,9 @@ static Rpc { @@ -41,7 +44,7 @@ static Rpc WeaviateBlockingStub::aggregate, - () -> WeaviateFutureStub::aggregate)); + () -> WeaviateFutureStub::aggregate); } static Rpc grouped( diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteManyRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteManyRequest.java index 5cbb64465..a472b918a 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteManyRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteManyRequest.java @@ -18,44 +18,48 @@ public record DeleteManyRequest(Where where, Boolean verbose, Boolean dryRun) { public static Rpc rpc( CollectionDescriptor collection, CollectionHandleDefaults defaults) { - return defaults.rpc( - Rpc - .of( - request -> { - var message = WeaviateProtoBatchDelete.BatchDeleteRequest.newBuilder(); - message.setCollection(collection.name()); - - if (request.verbose != null) { - message.setVerbose(request.verbose); - } - if (request.dryRun != null) { - message.setDryRun(request.dryRun); - } - - var filters = WeaviateProtoBase.Filters.newBuilder(); - request.where.appendTo(filters); - message.setFilters(filters); - - return message.build(); - }, - reply -> { - var objects = reply.getObjectsList() - .stream() - .map(obj -> new DeleteManyResponse.DeletedObject( - ByteStringUtil.decodeUuid(obj.getUuid()).toString(), - obj.getSuccessful(), - obj.getError())) - .toList(); - - return new DeleteManyResponse( - reply.getTook(), - reply.getFailed(), - reply.getMatches(), - reply.getSuccessful(), - objects); - }, - () -> WeaviateBlockingStub::batchDelete, - () -> WeaviateFutureStub::batchDelete)); + return Rpc.of( + request -> { + var message = WeaviateProtoBatchDelete.BatchDeleteRequest.newBuilder(); + message.setCollection(collection.name()); + + if (request.verbose != null) { + message.setVerbose(request.verbose); + } + if (request.dryRun != null) { + message.setDryRun(request.dryRun); + } + if (defaults.tenant() != null) { + message.setTenant(defaults.tenant()); + } + if (defaults.consistencyLevel() != null) { + defaults.consistencyLevel().appendTo(message); + } + + var filters = WeaviateProtoBase.Filters.newBuilder(); + request.where.appendTo(filters); + message.setFilters(filters); + + return message.build(); + }, + reply -> { + var objects = reply.getObjectsList() + .stream() + .map(obj -> new DeleteManyResponse.DeletedObject( + ByteStringUtil.decodeUuid(obj.getUuid()).toString(), + obj.getSuccessful(), + obj.getError())) + .toList(); + + return new DeleteManyResponse( + reply.getTook(), + reply.getFailed(), + reply.getMatches(), + reply.getSuccessful(), + objects); + }, + () -> WeaviateBlockingStub::batchDelete, + () -> WeaviateFutureStub::batchDelete); } public static DeleteManyRequest of(Where where) { diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteObjectRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteObjectRequest.java index 01efdb8fe..307dfd04f 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteObjectRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteObjectRequest.java @@ -1,9 +1,6 @@ package io.weaviate.client6.v1.api.collections.data; -import java.util.Collections; - import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; -import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults.Location; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; import io.weaviate.client6.v1.internal.rest.Endpoint; import io.weaviate.client6.v1.internal.rest.SimpleEndpoint; @@ -13,13 +10,9 @@ public record DeleteObjectRequest(String uuid) { public static final Endpoint endpoint( CollectionDescriptor collection, CollectionHandleDefaults defaults) { - return defaults.endpoint( - SimpleEndpoint.sideEffect( - request -> "DELETE", - request -> "/objects/" + collection.name() + "/" + request.uuid, - request -> Collections.emptyMap()), - add -> add - .consistencyLevel(Location.QUERY) - .tenant(Location.QUERY)); + return SimpleEndpoint.sideEffect( + request -> "DELETE", + request -> "/objects/" + collection.name() + "/" + request.uuid, + request -> defaults.queryParameters()); } } 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 d270fa336..261a69064 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 @@ -38,58 +38,62 @@ public static final InsertManyRequest of(T... properties) { public static Rpc, WeaviateProtoBatch.BatchObjectsRequest, InsertManyResponse, WeaviateProtoBatch.BatchObjectsReply> rpc( List> insertObjects, - CollectionDescriptor collectionsDescriptor, + CollectionDescriptor collection, CollectionHandleDefaults defaults) { - return defaults.rpc( - Rpc.of( - request -> { - var message = WeaviateProtoBatch.BatchObjectsRequest.newBuilder(); - - var batch = request.objects.stream().map(obj -> { - var batchObject = WeaviateProtoBatch.BatchObject.newBuilder(); - buildObject(batchObject, obj, collectionsDescriptor); - return batchObject.build(); - }).toList(); - - message.addAllObjects(batch); - return message.build(); - }, - response -> { - var insertErrors = response.getErrorsList(); - - var responses = new ArrayList(insertObjects.size()); - var errors = new ArrayList(insertErrors.size()); - var uuids = new ArrayList(); - - var failed = insertErrors.stream() - .collect(Collectors.toMap(err -> err.getIndex(), err -> err.getError())); - - var iter = insertObjects.listIterator(); - while (iter.hasNext()) { - var idx = iter.nextIndex(); - var next = iter.next(); - var uuid = next.metadata() != null ? next.metadata().uuid() : null; - - if (failed.containsKey(idx)) { - var err = failed.get(idx); - errors.add(err); - responses.add(new InsertManyResponse.InsertObject(uuid, false, err)); - } else { - uuids.add(uuid); - responses.add(new InsertManyResponse.InsertObject(uuid, true, null)); - } - } + return Rpc.of( + request -> { + var message = WeaviateProtoBatch.BatchObjectsRequest.newBuilder(); + + var batch = request.objects.stream().map(obj -> { + var batchObject = WeaviateProtoBatch.BatchObject.newBuilder(); + buildObject(batchObject, obj, collection, defaults); + return batchObject.build(); + }).toList(); + + message.addAllObjects(batch); + + if (defaults.consistencyLevel() != null) { + defaults.consistencyLevel().appendTo(message); + } + return message.build(); + }, + response -> { + var insertErrors = response.getErrorsList(); + + var responses = new ArrayList(insertObjects.size()); + var errors = new ArrayList(insertErrors.size()); + var uuids = new ArrayList(); + + var failed = insertErrors.stream() + .collect(Collectors.toMap(err -> err.getIndex(), err -> err.getError())); + + var iter = insertObjects.listIterator(); + while (iter.hasNext()) { + var idx = iter.nextIndex(); + var next = iter.next(); + var uuid = next.metadata() != null ? next.metadata().uuid() : null; + + if (failed.containsKey(idx)) { + var err = failed.get(idx); + errors.add(err); + responses.add(new InsertManyResponse.InsertObject(uuid, false, err)); + } else { + uuids.add(uuid); + responses.add(new InsertManyResponse.InsertObject(uuid, true, null)); + } + } - return new InsertManyResponse(response.getTook(), responses, uuids, errors); - }, - () -> WeaviateBlockingStub::batchObjects, - () -> WeaviateFutureStub::batchObjects)); + return new InsertManyResponse(response.getTook(), responses, uuids, errors); + }, + () -> WeaviateBlockingStub::batchObjects, + () -> WeaviateFutureStub::batchObjects); } public static void buildObject(WeaviateProtoBatch.BatchObject.Builder object, WeaviateObject insert, - CollectionDescriptor collectionDescriptor) { - object.setCollection(collectionDescriptor.name()); + CollectionDescriptor collection, + CollectionHandleDefaults defaults) { + object.setCollection(collection.name()); var metadata = insert.metadata(); if (metadata != null) { @@ -116,6 +120,9 @@ public static void buildObject(WeaviateProtoBatch.BatchObject.Builder object }).toList(); object.addAllVectors(vectors); } + if (defaults.tenant() != null) { + object.setTenant(defaults.tenant()); + } } var properties = WeaviateProtoBatch.BatchObject.Properties.newBuilder(); @@ -123,7 +130,7 @@ public static void buildObject(WeaviateProtoBatch.BatchObject.Builder object var singleRef = new ArrayList(); var multiRef = new ArrayList(); - collectionDescriptor + collection .propertiesReader(insert.properties()).readProperties() .entrySet().stream().forEach(entry -> { var value = entry.getValue(); 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 311ee462d..972be0183 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 @@ -1,12 +1,12 @@ package io.weaviate.client6.v1.api.collections.data; import java.util.Collections; +import java.util.Map; import java.util.function.Function; import com.google.gson.reflect.TypeToken; import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; -import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults.Location; import io.weaviate.client6.v1.api.collections.ObjectMetadata; import io.weaviate.client6.v1.api.collections.Vectors; import io.weaviate.client6.v1.api.collections.WeaviateObject; @@ -22,20 +22,19 @@ public record InsertObjectRequest(WeaviateObject Endpoint, WeaviateObject> endpoint( CollectionDescriptor collection, CollectionHandleDefaults defaults) { - return defaults.endpoint( - new SimpleEndpoint<>( - request -> "POST", - request -> "/objects/", - request -> Collections.emptyMap(), - request -> 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))), - add -> add - .consistencyLevel(Location.QUERY)); + return new SimpleEndpoint<>( + request -> "POST", + request -> "/objects/", + 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())), + (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) { diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceAddManyRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceAddManyRequest.java index 1ca2591f8..284688daa 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceAddManyRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceAddManyRequest.java @@ -1,11 +1,9 @@ package io.weaviate.client6.v1.api.collections.data; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; -import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults.Location; import io.weaviate.client6.v1.internal.json.JSON; import io.weaviate.client6.v1.internal.rest.Endpoint; import io.weaviate.client6.v1.internal.rest.SimpleEndpoint; @@ -15,27 +13,23 @@ public record ReferenceAddManyRequest(List references) { public static final Endpoint endpoint( List references, CollectionHandleDefaults defaults) { - return defaults.endpoint( - new SimpleEndpoint<>( - request -> "POST", - request -> "/batch/references", - request -> Collections.emptyMap(), - request -> JSON.serialize(request.references), - (statusCode, response) -> { - var result = JSON.deserialize(response, ReferenceAddManyResponse.class); - var errors = new ArrayList(); + return new SimpleEndpoint<>( + request -> "POST", + request -> "/batch/references", + request -> defaults.queryParameters(), + request -> JSON.serialize(request.references), + (statusCode, response) -> { + var result = JSON.deserialize(response, ReferenceAddManyResponse.class); + var errors = new ArrayList(); - for (var err : result.errors()) { - errors.add(new ReferenceAddManyResponse.BatchError( - err.message(), - references.get(err.referenceIndex()), - err.referenceIndex())); - } - return new ReferenceAddManyResponse(errors); - }), - add -> add - .consistencyLevel(Location.QUERY) - .tenant(Location.QUERY)); + for (var err : result.errors()) { + errors.add(new ReferenceAddManyResponse.BatchError( + err.message(), + references.get(err.referenceIndex()), + err.referenceIndex())); + } + return new ReferenceAddManyResponse(errors); + }); } } 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 cb608e460..89201f4de 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 @@ -1,9 +1,6 @@ package io.weaviate.client6.v1.api.collections.data; -import java.util.Collections; - import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; -import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults.Location; import io.weaviate.client6.v1.internal.json.JSON; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; import io.weaviate.client6.v1.internal.rest.Endpoint; @@ -13,16 +10,12 @@ public record ReferenceAddRequest(String fromUuid, String fromProperty, Referenc public static final Endpoint endpoint( CollectionDescriptor descriptor, - CollectionHandleDefaults defautls) { - return defautls.endpoint( - SimpleEndpoint.sideEffect( - request -> "POST", - request -> "/objects/" + descriptor.name() + "/" + request.fromUuid + "/references/" + request.fromProperty, - request -> Collections.emptyMap(), - request -> JSON.serialize(request.reference)), - add -> add - .consistencyLevel(Location.QUERY) - .tenant(Location.QUERY)); + CollectionHandleDefaults defaults) { + return SimpleEndpoint.sideEffect( + request -> "POST", + request -> "/objects/" + descriptor.name() + "/" + request.fromUuid + "/references/" + request.fromProperty, + request -> defaults.queryParameters(), + request -> JSON.serialize(request.reference)); } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceDeleteRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceDeleteRequest.java index f9bb17ebc..fc53457ae 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceDeleteRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceDeleteRequest.java @@ -1,9 +1,6 @@ package io.weaviate.client6.v1.api.collections.data; -import java.util.Collections; - import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; -import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults.Location; import io.weaviate.client6.v1.internal.json.JSON; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; import io.weaviate.client6.v1.internal.rest.Endpoint; @@ -14,14 +11,10 @@ public record ReferenceDeleteRequest(String fromUuid, String fromProperty, Refer public static final Endpoint endpoint( CollectionDescriptor descriptor, CollectionHandleDefaults defaults) { - return defaults.endpoint( - SimpleEndpoint.sideEffect( - request -> "DELETE", - request -> "/objects/" + descriptor.name() + "/" + request.fromUuid + "/references/" + request.fromProperty, - request -> Collections.emptyMap(), - request -> JSON.serialize(request.reference)), - add -> add - .consistencyLevel(Location.QUERY) - .tenant(Location.QUERY)); + return SimpleEndpoint.sideEffect( + request -> "DELETE", + request -> "/objects/" + descriptor.name() + "/" + request.fromUuid + "/references/" + request.fromProperty, + request -> defaults.queryParameters(), + request -> JSON.serialize(request.reference)); } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceReplaceRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceReplaceRequest.java index 2faf1cb6a..13516d0ac 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceReplaceRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/ReferenceReplaceRequest.java @@ -1,10 +1,8 @@ package io.weaviate.client6.v1.api.collections.data; -import java.util.Collections; import java.util.List; import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; -import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults.Location; import io.weaviate.client6.v1.internal.json.JSON; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; import io.weaviate.client6.v1.internal.rest.Endpoint; @@ -15,14 +13,10 @@ public record ReferenceReplaceRequest(String fromUuid, String fromProperty, Refe public static final Endpoint endpoint( CollectionDescriptor descriptor, CollectionHandleDefaults defaults) { - return defaults.endpoint( - SimpleEndpoint.sideEffect( - request -> "PUT", - request -> "/objects/" + descriptor.name() + "/" + request.fromUuid + "/references/" + request.fromProperty, - request -> Collections.emptyMap(), - request -> JSON.serialize(List.of(request.reference))), - add -> add - .consistencyLevel(Location.QUERY) - .tenant(Location.QUERY)); + return SimpleEndpoint.sideEffect( + request -> "PUT", + request -> "/objects/" + descriptor.name() + "/" + request.fromUuid + "/references/" + request.fromProperty, + request -> defaults.queryParameters(), + request -> JSON.serialize(List.of(request.reference))); } } 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 19ca5386f..e327c4999 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 @@ -1,12 +1,12 @@ package io.weaviate.client6.v1.api.collections.data; import java.util.Collections; +import java.util.Map; import java.util.function.Function; import com.google.gson.reflect.TypeToken; import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; -import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults.Location; import io.weaviate.client6.v1.api.collections.ObjectMetadata; import io.weaviate.client6.v1.api.collections.Vectors; import io.weaviate.client6.v1.api.collections.WeaviateObject; @@ -20,17 +20,15 @@ public record ReplaceObjectRequest(WeaviateObject Endpoint, Void> endpoint(CollectionDescriptor collection, CollectionHandleDefaults defaults) { - return defaults.endpoint( - SimpleEndpoint.sideEffect( - request -> "PUT", - request -> "/objects/" + collection.name() + "/" + request.object.metadata().uuid(), - request -> Collections.emptyMap(), - request -> JSON.serialize( - new WriteWeaviateObject<>(request.object, defaults.tenant()), - TypeToken.getParameterized(WriteWeaviateObject.class, collection.typeToken().getType()))), - add -> add - .consistencyLevel(Location.QUERY) - .tenant(Location.BODY)); + return SimpleEndpoint.sideEffect( + request -> "PUT", + request -> "/objects/" + collection.name() + "/" + request.object.metadata().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()))); } public static ReplaceObjectRequest of(String collectionName, String uuid, 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 ada6c47b6..f50a76ad2 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 @@ -1,12 +1,12 @@ package io.weaviate.client6.v1.api.collections.data; import java.util.Collections; +import java.util.Map; import java.util.function.Function; import com.google.gson.reflect.TypeToken; import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; -import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults.Location; import io.weaviate.client6.v1.api.collections.ObjectMetadata; import io.weaviate.client6.v1.api.collections.Vectors; import io.weaviate.client6.v1.api.collections.WeaviateObject; @@ -20,17 +20,15 @@ public record UpdateObjectRequest(WeaviateObject Endpoint, Void> endpoint(CollectionDescriptor collection, CollectionHandleDefaults defaults) { - return defaults.endpoint( - SimpleEndpoint.sideEffect( - request -> "PATCH", - request -> "/objects/" + collection.name() + "/" + request.object.metadata().uuid(), - request -> Collections.emptyMap(), - request -> JSON.serialize( - new WriteWeaviateObject<>(request.object, defaults.tenant()), - TypeToken.getParameterized(WriteWeaviateObject.class, collection.typeToken().getType()))), - add -> add - .consistencyLevel(Location.QUERY) - .tenant(Location.BODY)); + return SimpleEndpoint.sideEffect( + request -> "PATCH", + request -> "/objects/" + collection.name() + "/" + request.object.metadata().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()))); } public static UpdateObjectRequest of(String collectionName, String uuid, diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryRequest.java index 2d59e9aa6..a14be5794 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/QueryRequest.java @@ -27,7 +27,7 @@ public record QueryRequest(QueryOperator operator, GroupBy groupBy) { static Rpc, WeaviateProtoSearchGet.SearchReply> rpc( CollectionDescriptor collection, CollectionHandleDefaults defaults) { - return defaults.rpc(Rpc.of( + return Rpc.of( request -> { var message = WeaviateProtoSearchGet.SearchRequest.newBuilder(); message.setUses127Api(true); @@ -35,6 +35,14 @@ static Rpc Rpc(objects); }, () -> WeaviateBlockingStub::search, - () -> WeaviateFutureStub::search)); + () -> WeaviateFutureStub::search); } static Rpc, WeaviateProtoSearchGet.SearchReply> grouped( diff --git a/src/test/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientTest.java b/src/test/java/io/weaviate/client6/v1/api/collections/CollectionHandleTest.java similarity index 50% rename from src/test/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientTest.java rename to src/test/java/io/weaviate/client6/v1/api/collections/CollectionHandleTest.java index c7c229dbf..c727ba50d 100644 --- a/src/test/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientTest.java +++ b/src/test/java/io/weaviate/client6/v1/api/collections/CollectionHandleTest.java @@ -1,4 +1,4 @@ -package io.weaviate.client6.v1.api.collections.data; +package io.weaviate.client6.v1.api.collections; import java.util.Map; @@ -13,8 +13,8 @@ import com.jparams.junit4.data.DataMethod; import com.jparams.junit4.description.Name; -import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; -import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults.Location; +import io.weaviate.client6.v1.api.collections.data.Reference; +import io.weaviate.client6.v1.api.collections.data.WeaviateDataClient; import io.weaviate.client6.v1.api.collections.query.ConsistencyLevel; import io.weaviate.client6.v1.internal.ObjectBuilder; import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBase; @@ -24,7 +24,7 @@ import io.weaviate.testutil.transport.MockRestTransport; @RunWith(JParamsTestRunner.class) -public class WeaviateDataClientTest { +public class CollectionHandleTest { private static MockRestTransport rest; private static MockGrpcTransport grpc; @@ -42,64 +42,75 @@ public static void tearDown() throws Exception { @FunctionalInterface interface Act { - void apply(WeaviateDataClient> client) throws Exception; + void apply(CollectionHandle> client) throws Exception; + } + + /** Which part of the request a parameter should be added to. */ + public static enum Location { + /** Query string. */ + QUERY, + /** + * Request body. {@code RequestT} must implement {@link WithDefaults} for the + * changes to be applied. + */ + BODY; } public static Object[][] restTestCases() { return new Object[][] { { - "insert single object", + "data::insert single object", ConsistencyLevel.ONE, Location.QUERY, "john_doe", Location.BODY, - (Act) client -> client.insert(Map.of()), + (Act) c -> c.data.insert(Map.of()), }, { - "replace single object", + "data::replace single object", ConsistencyLevel.ONE, Location.QUERY, "john_doe", Location.BODY, - (Act) client -> client.replace("test-uuid", ObjectBuilder.identity()), + (Act) c -> c.data.replace("test-uuid", ObjectBuilder.identity()), }, { - "update single object", + "data::update single object", ConsistencyLevel.ONE, Location.QUERY, "john_doe", Location.BODY, - (Act) client -> client.update("test-uuid", ObjectBuilder.identity()), + (Act) c -> c.data.update("test-uuid", ObjectBuilder.identity()), }, { - "delete by id", + "data::delete by id", ConsistencyLevel.ONE, Location.QUERY, "john_doe", Location.QUERY, - (Act) client -> client.delete("test-uuid"), + (Act) c -> c.data.delete("test-uuid"), }, { - "add reference", + "data::add reference", ConsistencyLevel.ONE, Location.QUERY, "john_doe", Location.QUERY, - (Act) client -> client.referenceAdd("from-uuid", "from_property", Reference.uuids("to-uuid")), + (Act) c -> c.data.referenceAdd("from-uuid", "from_property", Reference.uuids("to-uuid")), }, { - "add reference many", + "data::add reference many", ConsistencyLevel.ONE, Location.QUERY, "john_doe", Location.QUERY, - (Act) client -> client.referenceAddMany(), + (Act) c -> c.data.referenceAddMany(), }, { - "replace reference", + "data::replace reference", ConsistencyLevel.ONE, Location.QUERY, "john_doe", Location.QUERY, - (Act) client -> client.referenceReplace("from-uuid", "from_property", Reference.uuids("to-uuid")), + (Act) c -> c.data.referenceReplace("from-uuid", "from_property", Reference.uuids("to-uuid")), }, { - "delete reference", + "data::delete reference", ConsistencyLevel.ONE, Location.QUERY, "john_doe", Location.QUERY, - (Act) client -> client.referenceDelete("from-uuid", "from_property", Reference.uuids("to-uuid")), + (Act) c -> c.data.referenceDelete("from-uuid", "from_property", Reference.uuids("to-uuid")), }, }; } @Name("{0}") - @DataMethod(source = WeaviateDataClientTest.class, method = "restTestCases") + @DataMethod(source = CollectionHandleTest.class, method = "restTestCases") @Test public void test_collectionHandleDefaults_rest(String __, ConsistencyLevel cl, Location clLoc, @@ -111,8 +122,7 @@ public void test_collectionHandleDefaults_rest(String __, var defaults = CollectionHandleDefaults.of(d -> d .consistencyLevel(cl) .tenant(tenant)); - var client = new WeaviateDataClient>( - collection, rest, null, defaults); + var client = new CollectionHandle>(rest, grpc, collection, defaults); // Act act.apply(client); @@ -137,34 +147,50 @@ public void test_collectionHandleDefaults_rest(String __, }); } - private void assertJsonHasValue(String json, String key, T value) { - var gotJson = JsonParser.parseString(json).getAsJsonObject(); - Assertions.assertThat(gotJson.has(key)) - .describedAs("missing key \"%s\" in %s", key, json) - .isTrue(); - - var wantValue = JsonParser.parseString(JSON.serialize(value)); - Assertions.assertThat(gotJson.get(key)).isEqualTo(wantValue); - } - public static Object[][] grpcTestCases() { return new Object[][] { - { "object exists", (Act) client -> client.exists("test-uuid") }, - { "delete many", (Act) client -> client.deleteMany() }, + { "data::object exists", (Act) c -> c.data.exists("test-uuid") }, + { "data::delete many", (Act) c -> c.data.deleteMany() }, + + { "query::get by id", (Act) c -> c.query.byId("test-uuid") }, + { "query::fetch objects", (Act) c -> c.query.fetchObjects(ObjectBuilder.identity()) }, + { "query::bm25", (Act) c -> c.query.bm25("red ballon") }, + { "query::hybrid", (Act) c -> c.query.hybrid("red ballon") }, + { "query::nearVector", (Act) c -> c.query.nearVector(new float[] {}) }, + { "query::nearText", (Act) c -> c.query.nearText("weather in Arizona") }, + { "query::nearObject", (Act) c -> c.query.nearObject("test-uuid") }, + { "query::nearImage", (Act) c -> c.query.nearImage("img.jpeg") }, + { "query::nearAudio", (Act) c -> c.query.nearAudio("song.mp3") }, + { "query::nearVideo", (Act) c -> c.query.nearVideo("clip.mp4") }, + { "query::nearDepth", (Act) c -> c.query.nearDepth("20.000 leagues") }, + { "query::nearThermal", (Act) c -> c.query.nearThermal("Fahrenheit 451") }, + { "query::nearImu", (Act) c -> c.query.nearImu("6 m/s") }, + + { "aggregate::over all", (Act) c -> c.aggregate.overAll(ObjectBuilder.identity()), true }, + { "aggregate::hybrid", (Act) c -> c.aggregate.hybrid("red balloon", ObjectBuilder.identity()), true }, + { "aggregate::nearVector", (Act) c -> c.aggregate.nearVector(new float[] {}, ObjectBuilder.identity()), true }, + { "aggregate::nearText", (Act) c -> c.aggregate.nearText("red balloon", ObjectBuilder.identity()), true }, + { "aggregate::nearObject", (Act) c -> c.aggregate.nearObject("test-uuid", ObjectBuilder.identity()), true }, + { "aggregate::nearImage", (Act) c -> c.aggregate.nearImage("img.jpeg", ObjectBuilder.identity()), true }, + { "aggregate::nearAudio", (Act) c -> c.aggregate.nearAudio("song.mp3", ObjectBuilder.identity()), true }, + { "aggregate::nearVideo", (Act) c -> c.aggregate.nearVideo("clip.mp4", ObjectBuilder.identity()), true }, + { "aggregate::nearDepth", (Act) c -> c.aggregate.nearDepth("20.000 leagues", ObjectBuilder.identity()), true }, + { "aggregate::nearThermal", (Act) c -> c.aggregate.nearThermal("Fahrenheit 451", ObjectBuilder.identity()), + true }, + { "aggregate::nearImu", (Act) c -> c.aggregate.nearImu("6 m/s", ObjectBuilder.identity()), true }, }; } @Name("{0}") - @DataMethod(source = WeaviateDataClientTest.class, method = "grpcTestCases") + @DataMethod(source = CollectionHandleTest.class, method = "grpcTestCases") @Test - public void test_collectionHandleDefaults_grpc(String __, Act act) throws Exception { + public void test_collectionHandleDefaults_grpc(String __, Act act, Boolean skipConsistency) throws Exception { // Arrange var collection = CollectionDescriptor.ofMap("Things"); var defaults = CollectionHandleDefaults.of(d -> d .consistencyLevel(ConsistencyLevel.ONE) .tenant("john_doe")); - var client = new WeaviateDataClient>( - collection, null, grpc, defaults); + var client = new CollectionHandle>(rest, grpc, collection, defaults); // Act act.apply(client); @@ -172,8 +198,11 @@ public void test_collectionHandleDefaults_grpc(String __, Act act) throws Except // Assert grpc.assertNext(json -> { assertJsonHasValue(json, "tenant", "john_doe"); - assertJsonHasValue(json, "consistencyLevel", - WeaviateProtoBase.ConsistencyLevel.CONSISTENCY_LEVEL_ONE.toString()); + + if (skipConsistency != null && !skipConsistency) { + assertJsonHasValue(json, "consistencyLevel", + WeaviateProtoBase.ConsistencyLevel.CONSISTENCY_LEVEL_ONE.toString()); + } }); } @@ -198,4 +227,14 @@ public void test_defaultTenant_insertMany() { WeaviateProtoBase.ConsistencyLevel.CONSISTENCY_LEVEL_ONE.toString()); }); } + + private static void assertJsonHasValue(String json, String key, T value) { + var gotJson = JsonParser.parseString(json).getAsJsonObject(); + Assertions.assertThat(gotJson.has(key)) + .describedAs("missing key \"%s\" in %s", key, json) + .isTrue(); + + var wantValue = JsonParser.parseString(JSON.serialize(value)); + Assertions.assertThat(gotJson.get(key)).isEqualTo(wantValue); + } } diff --git a/src/test/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClientTest.java b/src/test/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClientTest.java deleted file mode 100644 index 74e611b62..000000000 --- a/src/test/java/io/weaviate/client6/v1/api/collections/aggregate/WeaviateAggregateClientTest.java +++ /dev/null @@ -1,84 +0,0 @@ -package io.weaviate.client6.v1.api.collections.aggregate; - -import org.assertj.core.api.Assertions; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; - -import com.google.gson.JsonParser; -import com.jparams.junit4.JParamsTestRunner; -import com.jparams.junit4.data.DataMethod; -import com.jparams.junit4.description.Name; - -import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; -import io.weaviate.client6.v1.api.collections.query.ConsistencyLevel; -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.testutil.transport.MockGrpcTransport; - -@RunWith(JParamsTestRunner.class) -public class WeaviateAggregateClientTest { - private static MockGrpcTransport grpc; - - @BeforeClass - public static void setUp() { - grpc = new MockGrpcTransport(); - } - - @AfterClass - public static void tearDown() throws Exception { - grpc.close(); - } - - @FunctionalInterface - interface Act { - void apply(WeaviateAggregateClient client) throws Exception; - } - - private void assertJsonHasValue(String json, String key, T value) { - var gotJson = JsonParser.parseString(json).getAsJsonObject(); - Assertions.assertThat(gotJson.has(key)) - .describedAs("missing key \"%s\" in %s", key, json) - .isTrue(); - - var wantValue = JsonParser.parseString(JSON.serialize(value)); - Assertions.assertThat(gotJson.get(key)).isEqualTo(wantValue); - } - - public static Object[][] grpcTestCases() { - return new Object[][] { - { "over all", (Act) client -> client.overAll(ObjectBuilder.identity()) }, - { "hybrid", (Act) client -> client.hybrid("red balloon", ObjectBuilder.identity()) }, - { "nearVector", (Act) client -> client.nearVector(new float[] {}, ObjectBuilder.identity()) }, - { "nearText", (Act) client -> client.nearText("red balloon", ObjectBuilder.identity()) }, - { "nearObject", (Act) client -> client.nearObject("test-uuid", ObjectBuilder.identity()) }, - { "nearImage", (Act) client -> client.nearImage("img.jpeg", ObjectBuilder.identity()) }, - { "nearAudio", (Act) client -> client.nearAudio("song.mp3", ObjectBuilder.identity()) }, - { "nearVideo", (Act) client -> client.nearVideo("clip.mp4", ObjectBuilder.identity()) }, - { "nearDepth", (Act) client -> client.nearDepth("20.000 leagues", ObjectBuilder.identity()) }, - { "nearThermal", (Act) client -> client.nearThermal("Fahrenheit 451", ObjectBuilder.identity()) }, - { "nearImu", (Act) client -> client.nearImu("6 m/s", ObjectBuilder.identity()) }, - }; - } - - @Name("{0}") - @DataMethod(source = WeaviateAggregateClientTest.class, method = "grpcTestCases") - @Test - public void test_collectionHandleDefaults_grpc(String __, Act act) - throws Exception { - // Arrange - var collection = CollectionDescriptor.ofMap("Things"); - var defaults = CollectionHandleDefaults.of(d -> d - .consistencyLevel(ConsistencyLevel.ONE) - .tenant("john_doe")); - var client = new WeaviateAggregateClient(collection, grpc, defaults); - - // Act - act.apply(client); - - // Assert - grpc.assertNext(json -> assertJsonHasValue(json, "tenant", "john_doe")); - } -} diff --git a/src/test/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientTest.java b/src/test/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientTest.java deleted file mode 100644 index 38ce03b74..000000000 --- a/src/test/java/io/weaviate/client6/v1/api/collections/query/WeaviateQueryClientTest.java +++ /dev/null @@ -1,92 +0,0 @@ -package io.weaviate.client6.v1.api.collections.query; - -import java.util.Map; - -import org.assertj.core.api.Assertions; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; - -import com.google.gson.JsonParser; -import com.jparams.junit4.JParamsTestRunner; -import com.jparams.junit4.data.DataMethod; -import com.jparams.junit4.description.Name; - -import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; -import io.weaviate.client6.v1.internal.ObjectBuilder; -import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBase; -import io.weaviate.client6.v1.internal.json.JSON; -import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; -import io.weaviate.testutil.transport.MockGrpcTransport; - -@RunWith(JParamsTestRunner.class) -public class WeaviateQueryClientTest { - private static MockGrpcTransport grpc; - - @BeforeClass - public static void setUp() { - grpc = new MockGrpcTransport(); - } - - @AfterClass - public static void tearDown() throws Exception { - grpc.close(); - } - - @FunctionalInterface - interface Act { - void apply(WeaviateQueryClient> client) throws Exception; - } - - private void assertJsonHasValue(String json, String key, T value) { - var gotJson = JsonParser.parseString(json).getAsJsonObject(); - Assertions.assertThat(gotJson.has(key)) - .describedAs("missing key \"%s\" in %s", key, json) - .isTrue(); - - var wantValue = JsonParser.parseString(JSON.serialize(value)); - Assertions.assertThat(gotJson.get(key)).isEqualTo(wantValue); - } - - public static Object[][] grpcTestCases() { - return new Object[][] { - { "get by id", (Act) client -> client.byId("test-uuid") }, - { "fetch objects", (Act) client -> client.fetchObjects(ObjectBuilder.identity()) }, - { "bm25", (Act) client -> client.bm25("red ballon") }, - { "hybrid", (Act) client -> client.hybrid("red ballon") }, - { "nearVector", (Act) client -> client.nearVector(new float[] {}) }, - { "nearText", (Act) client -> client.nearText("weather in Arizona") }, - { "nearObject", (Act) client -> client.nearObject("test-uuid") }, - { "nearImage", (Act) client -> client.nearImage("img.jpeg") }, - { "nearAudio", (Act) client -> client.nearAudio("song.mp3") }, - { "nearVideo", (Act) client -> client.nearVideo("clip.mp4") }, - { "nearDepth", (Act) client -> client.nearDepth("20.000 leagues") }, - { "nearThermal", (Act) client -> client.nearThermal("Fahrenheit 451") }, - { "nearImu", (Act) client -> client.nearImu("6 m/s") }, - }; - } - - @Name("{0}") - @DataMethod(source = WeaviateQueryClientTest.class, method = "grpcTestCases") - @Test - public void test_collectionHandleDefaults_grpc(String __, Act act) - throws Exception { - // Arrange - var collection = CollectionDescriptor.ofMap("Things"); - var defaults = CollectionHandleDefaults.of(d -> d - .consistencyLevel(ConsistencyLevel.ONE) - .tenant("john_doe")); - var client = new WeaviateQueryClient>(collection, grpc, defaults); - - // Act - act.apply(client); - - // Assert - grpc.assertNext(json -> { - assertJsonHasValue(json, "tenant", "john_doe"); - assertJsonHasValue(json, "consistencyLevel", - WeaviateProtoBase.ConsistencyLevel.CONSISTENCY_LEVEL_ONE.toString()); - }); - } -} From 68978c8c4e92cb696d85aeaa0ba49cff55e9c0e8 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Thu, 21 Aug 2025 23:07:49 +0200 Subject: [PATCH 15/24] refactor: remove unnecessary abstraction This method is only used in one place, inlining it makes more sense. --- .../v1/internal/rest/DefaultRestTransport.java | 10 +++++++++- .../client6/v1/internal/rest/EndpointBase.java | 13 ------------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/main/java/io/weaviate/client6/v1/internal/rest/DefaultRestTransport.java b/src/main/java/io/weaviate/client6/v1/internal/rest/DefaultRestTransport.java index 99d5bcb42..f8b4d255b 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/rest/DefaultRestTransport.java +++ b/src/main/java/io/weaviate/client6/v1/internal/rest/DefaultRestTransport.java @@ -165,13 +165,21 @@ private ResponseT handleResponseAsync( return _handleResponse(endpoint, method, url, statusCode, body); } + @SuppressWarnings("unchecked") private ResponseT _handleResponse(Endpoint endpoint, String method, String url, int statusCode, String body) { if (endpoint.isError(statusCode)) { var message = endpoint.deserializeError(statusCode, body); throw WeaviateApiException.http(method, url, statusCode, message); } - return EndpointBase.deserializeResponse(endpoint, statusCode, body); + if (endpoint instanceof JsonEndpoint json) { + return (ResponseT) json.deserializeResponse(statusCode, body); + } else if (endpoint instanceof BooleanEndpoint bool) { + return (ResponseT) ((Boolean) bool.getResult(statusCode)); + } + + // TODO: make it a WeaviateTransportException + throw new RuntimeException("Unhandled endpoint type " + endpoint.getClass().getSimpleName()); } @Override diff --git a/src/main/java/io/weaviate/client6/v1/internal/rest/EndpointBase.java b/src/main/java/io/weaviate/client6/v1/internal/rest/EndpointBase.java index d38622915..50bd9069a 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/rest/EndpointBase.java +++ b/src/main/java/io/weaviate/client6/v1/internal/rest/EndpointBase.java @@ -67,19 +67,6 @@ public String deserializeError(int statusCode, String responseBody) { return response.errors.get(0).text(); } - @SuppressWarnings("unchecked") - public static ResponseT deserializeResponse(Endpoint endpoint, int statusCode, - String responseBody) { - if (endpoint instanceof JsonEndpoint json) { - return (ResponseT) json.deserializeResponse(statusCode, responseBody); - } else if (endpoint instanceof BooleanEndpoint bool) { - return (ResponseT) ((Boolean) bool.getResult(statusCode)); - } - - // TODO: make it a WeaviateTransportException - throw new RuntimeException("Unhandled endpoint type " + endpoint.getClass().getSimpleName()); - } - static record ErrorResponse(@SerializedName("error") List errors) { private static record ErrorMessage(@SerializedName("message") String text) { } From 4b52821650343582d26fa043a4033eb582fc57ff Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Thu, 21 Aug 2025 23:17:00 +0200 Subject: [PATCH 16/24] feat: filter out invalid (null/blank) query parameters --- .../client6/v1/internal/rest/UrlEncoder.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/weaviate/client6/v1/internal/rest/UrlEncoder.java b/src/main/java/io/weaviate/client6/v1/internal/rest/UrlEncoder.java index 9c0f5f6ee..b4a9d2b67 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/rest/UrlEncoder.java +++ b/src/main/java/io/weaviate/client6/v1/internal/rest/UrlEncoder.java @@ -6,7 +6,7 @@ import java.util.Map; import java.util.stream.Collectors; -public final class UrlEncoder { +final class UrlEncoder { private static String encodeValue(Object value) { try { @@ -16,11 +16,28 @@ private static String encodeValue(Object value) { } } + /** + * Encodes each key-value pair into a URL-compatible query string, omitting any + * {@code null} or blank (in case of String parameter) values. + * Each value is represented by the return of its [@conde toString()} method. + * + * @return URL query string or empty string if the map was empty + * or contained no valid parameters. + */ public static String encodeQuery(Map queryParams) { if (queryParams == null || queryParams.isEmpty()) { return ""; } return queryParams.entrySet().stream() + .filter(qp -> { + if (qp == null) { + return false; + } + if (qp.getValue() instanceof String str) { + return !str.isBlank(); + } + return true; + }) .map(qp -> qp.getKey() + "=" + encodeValue(qp.getValue())) .collect(Collectors.joining("&", "?", "")); } From 904bac21d02b26dd5920de893c9f30f3197ed7fb Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Thu, 21 Aug 2025 23:29:09 +0200 Subject: [PATCH 17/24] feat: add withTenant and withDefaults to CollectionHandleAsync --- .../collections/CollectionHandleAsync.java | 13 +++++++++ .../CollectionHandleDefaultsTest.java | 27 +++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleAsync.java b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleAsync.java index dccc85dcd..f43b3cfe7 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleAsync.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleAsync.java @@ -89,4 +89,17 @@ public CollectionHandleAsync withConsistencyLevel(ConsistencyLevel return new CollectionHandleAsync<>(this, CollectionHandleDefaults.of( def -> def.consistencyLevel(consistencyLevel))); } + + public String tenant() { + return defaults.tenant(); + } + + public CollectionHandleAsync withTenant(String tenant) { + return new CollectionHandleAsync<>(this, CollectionHandleDefaults.of(with -> with.tenant(tenant))); + } + + public CollectionHandleAsync withDefaults( + Function> fn) { + return new CollectionHandleAsync<>(this, CollectionHandleDefaults.of(fn)); + } } diff --git a/src/test/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaultsTest.java b/src/test/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaultsTest.java index 1c0d7aff2..4b420b3fd 100644 --- a/src/test/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaultsTest.java +++ b/src/test/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaultsTest.java @@ -24,7 +24,8 @@ public class CollectionHandleDefaultsTest { /** All defaults are {@code null} if none were set. */ @Test public void test_defaults() { - Assertions.assertThat(HANDLE_NONE.consistencyLevel()).isNull(); + Assertions.assertThat(HANDLE_NONE.consistencyLevel()).as("default ConsistencyLevel").isNull(); + Assertions.assertThat(HANDLE_NONE.tenant()).as("default tenant").isNull(); } /** @@ -39,7 +40,7 @@ public void test_withConsistencyLevel() { } /** - * {@link CollectionHandleAsync#withConsistencyLevel} should create a copy with + * {@link CollectionHandleAsync#withTenant} should create a copy with * different defaults but not modify the original. */ @Test @@ -48,4 +49,26 @@ public void test_withConsistencyLevel_async() { Assertions.assertThat(handle.consistencyLevel()).isEqualTo(ConsistencyLevel.QUORUM); Assertions.assertThat(HANDLE_NONE_ASYNC.consistencyLevel()).isNull(); } + + /** + * {@link CollectionHandle#withTenant} should create a copy with + * different defaults but not modify the original. + */ + @Test + public void test_withTenant() { + var handle = HANDLE_NONE.withTenant("john_doe"); + Assertions.assertThat(handle.tenant()).isEqualTo("john_doe"); + Assertions.assertThat(HANDLE_NONE.consistencyLevel()).isNull(); + } + + /** + * {@link CollectionHandleAsync#withTenant} should create a copy with + * different defaults but not modify the original. + */ + @Test + public void test_withTenant_async() { + var handle = HANDLE_NONE_ASYNC.withTenant("john_doe"); + Assertions.assertThat(handle.tenant()).isEqualTo("john_doe"); + Assertions.assertThat(HANDLE_NONE_ASYNC.consistencyLevel()).isNull(); + } } From 452ffc0b17469cf71a6e29a009ebf4b17771e966 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Thu, 21 Aug 2025 23:31:05 +0200 Subject: [PATCH 18/24] chore: delete unused variables --- .../client6/v1/api/collections/CollectionHandleDefaults.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java index b74447f6e..7ce9711ba 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/CollectionHandleDefaults.java @@ -9,9 +9,6 @@ import io.weaviate.client6.v1.internal.ObjectBuilder; public record CollectionHandleDefaults(ConsistencyLevel consistencyLevel, String tenant) { - private static final String CONSISTENCY_LEVEL = "consistency_level"; - private static final String TENANT = "tenant"; - /** * Set default values for query / aggregation requests. * From 9d35d741ff8cbe2d6b5fcad4d899408fe78bffeb Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Fri, 22 Aug 2025 19:14:02 +0200 Subject: [PATCH 19/24] feat: add tenants API --- pom.xml | 1 + src/it/java/io/weaviate/ConcurrentTest.java | 48 ++++++++++ .../io/weaviate/containers/Container.java | 1 + src/it/java/io/weaviate/containers/MinIo.java | 20 ++++ .../java/io/weaviate/containers/Weaviate.java | 9 ++ .../io/weaviate/integration/TenantsITest.java | 74 +++++++++++++++ .../v1/api/collections/CollectionHandle.java | 4 + .../v1/api/collections/MultiTenancy.java | 18 +++- .../tenants/CreateTenantsRequest.java | 19 ++++ .../tenants/DeleteTenantsRequest.java | 19 ++++ .../tenants/GetTenantsRequest.java | 57 +++++++++++ .../v1/api/collections/tenants/Tenant.java | 43 +++++++++ .../tenants/TenantExistsRequest.java | 17 ++++ .../api/collections/tenants/TenantStatus.java | 28 ++++++ .../tenants/UpdateTenantsRequest.java | 19 ++++ .../tenants/WeaviateTenantsClient.java | 94 +++++++++++++++++++ .../v1/internal/rest/BooleanEndpoint.java | 7 ++ .../v1/internal/rest/EndpointBase.java | 22 +++-- 18 files changed, 488 insertions(+), 12 deletions(-) create mode 100644 src/it/java/io/weaviate/containers/MinIo.java create mode 100644 src/it/java/io/weaviate/integration/TenantsITest.java create mode 100644 src/main/java/io/weaviate/client6/v1/api/collections/tenants/CreateTenantsRequest.java create mode 100644 src/main/java/io/weaviate/client6/v1/api/collections/tenants/DeleteTenantsRequest.java create mode 100644 src/main/java/io/weaviate/client6/v1/api/collections/tenants/GetTenantsRequest.java create mode 100644 src/main/java/io/weaviate/client6/v1/api/collections/tenants/Tenant.java create mode 100644 src/main/java/io/weaviate/client6/v1/api/collections/tenants/TenantExistsRequest.java create mode 100644 src/main/java/io/weaviate/client6/v1/api/collections/tenants/TenantStatus.java create mode 100644 src/main/java/io/weaviate/client6/v1/api/collections/tenants/UpdateTenantsRequest.java create mode 100644 src/main/java/io/weaviate/client6/v1/api/collections/tenants/WeaviateTenantsClient.java diff --git a/pom.xml b/pom.xml index bc4980990..c3175b555 100644 --- a/pom.xml +++ b/pom.xml @@ -244,6 +244,7 @@ maven-surefire-plugin 2.22.2 + false