diff --git a/src/it/java/io/weaviate/integration/PaginationITest.java b/src/it/java/io/weaviate/integration/PaginationITest.java new file mode 100644 index 000000000..961ad4df1 --- /dev/null +++ b/src/it/java/io/weaviate/integration/PaginationITest.java @@ -0,0 +1,160 @@ +package io.weaviate.integration; + +import static org.junit.Assume.assumeTrue; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.atomic.AtomicInteger; + +import org.assertj.core.api.Assertions; +import org.junit.Assume; +import org.junit.Test; + +import io.weaviate.ConcurrentTest; +import io.weaviate.client6.v1.api.WeaviateClient; +import io.weaviate.client6.v1.api.collections.Property; +import io.weaviate.client6.v1.api.collections.WeaviateMetadata; +import io.weaviate.client6.v1.api.collections.WeaviateObject; +import io.weaviate.containers.Container; + +public class PaginationITest extends ConcurrentTest { + private static WeaviateClient client = Container.WEAVIATE.getClient(); + + @Test + public void testIterateAll() throws IOException { + // Arrange + var nsThings = ns("Things"); + var count = 150; + + client.collections.create(nsThings); + var things = client.collections.use(nsThings); + + var inserted = new ArrayList(); + for (var i = 0; i < count; i++) { + var object = things.data.insert(Collections.emptyMap()); + inserted.add(object.metadata().uuid()); + } + assumeTrue("all objects were inserted", inserted.size() == count); + + var allThings = things.paginate(); + + // Act: stream + var gotStream = allThings.stream() + .map(WeaviateObject::metadata).map(WeaviateMetadata::uuid).toList(); + + // Assert + Assertions.assertThat(gotStream) + .as("stream fetched all objects") + .hasSize(inserted.size()) + .containsAll(inserted); + + // Act: for-loop + var gotLoop = new ArrayList(); + for (var thing : allThings) { + gotLoop.add(thing.metadata().uuid()); + } + + // Assert + Assertions.assertThat(gotLoop) + .as("list fetched all objects") + .hasSize(inserted.size()) + .containsAll(inserted); + + Assertions.assertThat(gotStream) + .as("stream and list return consistent order") + .containsExactlyElementsOf(gotLoop); + } + + @Test + public void testResumePagination() throws IOException { + // Arrange + var nsThings = ns("Things"); + var count = 10; + + client.collections.create(nsThings); + + var things = client.collections.use(nsThings); + var inserted = new ArrayList(); + for (var i = 0; i < count; i++) { + var object = things.data.insert(Collections.emptyMap()); + inserted.add(object.metadata().uuid()); + } + + // Iterate over first 5 objects + String lastId = things.paginate(p -> p.pageSize(5)).stream() + .limit(5).map(thing -> thing.metadata().uuid()) + .reduce((prev, next) -> next).get(); + + // Act + var remaining = things.paginate(p -> p.resumeFrom(lastId)).stream().count(); + + // Assert + Assertions.assertThat(remaining).isEqualTo(5); + } + + @Test + public void testWithQueryOptions() throws IOException { + // Arrange + var nsThings = ns("Things"); + var count = 10; + + client.collections.create(nsThings, + c -> c.properties( + Property.text("fetch_me"), + Property.integer("dont_fetch"))); + + var things = client.collections.use(nsThings); + var inserted = new ArrayList(); + for (var i = 0; i < count; i++) { + var object = things.data.insert(Collections.emptyMap()); + inserted.add(object.metadata().uuid()); + } + + // Act / Assert + var withSomeProperties = things.paginate(p -> p.returnProperties("fetch_me")); + for (var thing : withSomeProperties) { + Assertions.assertThat(thing.properties()) + .as("uuid=" + thing.metadata().uuid()) + .doesNotContainKey("dont_fetch"); + } + } + + @Test + public void testAsyncPaginator() throws IOException, InterruptedException, ExecutionException { + // Arrange + var nsThings = ns("Things"); + var count = 10; + + client.collections.create(nsThings); + + try (final var async = client.async()) { + var things = async.collections.use(nsThings); + + var futures = new CompletableFuture[count]; + var inserted = new ArrayList(); + for (var i = 0; i < count; i++) { + futures[i] = things.data.insert(Collections.emptyMap()) + .thenAccept(object -> inserted.add(object.metadata().uuid())); + } + CompletableFuture.allOf(futures).get(); + + // Act + var objectCount = new AtomicInteger(); + var countAll = things.paginate(p -> p.pageSize(5).prefetch(true)) + .forEach(__ -> objectCount.getAndIncrement()); + + // Assert + if (!countAll.isDone()) { + Assume.assumeTrue("iteration not completed", objectCount.get() < count); + } + + countAll.get(); // Wait for it to complete. + Assertions.assertThat(objectCount.get()) + .as("object count after iteration completed") + .isEqualTo(count); + } + } +} 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 2dd4529bd..802c324f1 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 @@ -1,9 +1,13 @@ package io.weaviate.client6.v1.api.collections; +import java.util.function.Function; + import io.weaviate.client6.v1.api.collections.aggregate.WeaviateAggregateClient; 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.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; @@ -24,4 +28,12 @@ public CollectionHandle( this.data = new WeaviateDataClient<>(collectionDescriptor, restTransport, this.query); this.aggregate = new WeaviateAggregateClient(collectionDescriptor, grpcTransport); } + + public Paginator paginate() { + return Paginator.of(this.query); + } + + public Paginator paginate(Function, ObjectBuilder>> fn) { + return Paginator.of(this.query, fn); + } } 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 ec41a5a21..b08bb2471 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 @@ -1,27 +1,40 @@ package io.weaviate.client6.v1.api.collections; +import java.util.function.Function; + import io.weaviate.client6.v1.api.collections.aggregate.WeaviateAggregateClientAsync; 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.WeaviateQueryClientAsync; +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 CollectionHandleAsync { +public class CollectionHandleAsync { public final WeaviateConfigClientAsync config; - public final WeaviateDataClientAsync data; - public final WeaviateQueryClientAsync query; + public final WeaviateDataClientAsync data; + public final WeaviateQueryClientAsync query; public final WeaviateAggregateClientAsync aggregate; public CollectionHandleAsync( RestTransport restTransport, GrpcTransport grpcTransport, - CollectionDescriptor collectionDescriptor) { + CollectionDescriptor collectionDescriptor) { this.config = new WeaviateConfigClientAsync(collectionDescriptor, restTransport, grpcTransport); this.query = new WeaviateQueryClientAsync<>(collectionDescriptor, grpcTransport); this.data = new WeaviateDataClientAsync<>(collectionDescriptor, restTransport, this.query); this.aggregate = new WeaviateAggregateClientAsync(collectionDescriptor, grpcTransport); } + + public AsyncPaginator paginate() { + return AsyncPaginator.of(this.query); + } + + public AsyncPaginator paginate( + Function, ObjectBuilder>> fn) { + return AsyncPaginator.of(this.query, fn); + } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPage.java b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPage.java new file mode 100644 index 000000000..54f45f945 --- /dev/null +++ b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPage.java @@ -0,0 +1,58 @@ +package io.weaviate.client6.v1.api.collections.pagination; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; + +import io.weaviate.client6.v1.api.collections.WeaviateObject; +import io.weaviate.client6.v1.api.collections.query.QueryMetadata; + +public final class AsyncPage implements Iterable> { + + private final int pageSize; + private final BiFunction>>> fetch; + + private final String cursor; + private List> currentPage = new ArrayList<>(); + + AsyncPage(String cursor, int pageSize, + BiFunction>>> fetch) { + this.cursor = cursor; + this.pageSize = pageSize; + this.fetch = fetch; + } + + AsyncPage(String cursor, int pageSize, + BiFunction>>> fetch, + List> currentPage) { + this(cursor, pageSize, fetch); + this.currentPage = Collections.unmodifiableList(currentPage); + } + + List> items() { + return currentPage; + } + + public boolean isEmpty() { + return this.currentPage.isEmpty(); + } + + public CompletableFuture> fetchNextPage() { + return fetch.apply(cursor, pageSize) + .thenApply(nextPage -> { + if (nextPage.isEmpty()) { + return new AsyncPage<>(null, pageSize, fetch, nextPage); + } + var last = nextPage.get(nextPage.size() - 1); + return new AsyncPage<>(last.metadata().uuid(), pageSize, fetch, nextPage); + }); + } + + @Override + public Iterator> iterator() { + return currentPage.iterator(); + } +} diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPaginator.java b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPaginator.java new file mode 100644 index 000000000..308a0327e --- /dev/null +++ b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/AsyncPaginator.java @@ -0,0 +1,154 @@ +package io.weaviate.client6.v1.api.collections.pagination; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import java.util.function.Function; + +import io.weaviate.client6.v1.api.collections.WeaviateObject; +import io.weaviate.client6.v1.api.collections.query.FetchObjects; +import io.weaviate.client6.v1.api.collections.query.Metadata; +import io.weaviate.client6.v1.api.collections.query.QueryMetadata; +import io.weaviate.client6.v1.api.collections.query.QueryReference; +import io.weaviate.client6.v1.api.collections.query.QueryResponse; +import io.weaviate.client6.v1.api.collections.query.WeaviateQueryClientAsync; +import io.weaviate.client6.v1.internal.ObjectBuilder; + +public class AsyncPaginator { + private final WeaviateQueryClientAsync query; + private final Function> queryOptions; + private final int pageSize; + private final String cursor; + + private CompletableFuture> resultSet; + + public AsyncPaginator(Builder builder) { + this.query = builder.query; + this.queryOptions = builder.queryOptions; + this.pageSize = builder.pageSize; + this.cursor = builder.cursor; + + var rs = new AsyncPage( + cursor, + pageSize, + (after, limit) -> { + var fn = ObjectBuilder.partial(queryOptions, q -> q.after(after).limit(limit)); + return this.query.fetchObjects(fn).thenApply(QueryResponse::objects); + }); + + this.resultSet = builder.prefetch ? rs.fetchNextPage() : CompletableFuture.completedFuture(rs); + } + + public CompletableFuture forEach(Consumer> action) { + return resultSet + .thenCompose(rs -> rs.isEmpty() ? rs.fetchNextPage() : CompletableFuture.completedFuture(rs)) + .thenCompose(processEachAndAdvance(action)); + } + + public CompletableFuture forPage(Consumer>> action) { + return resultSet + .thenCompose(rs -> rs.isEmpty() ? rs.fetchNextPage() : CompletableFuture.completedFuture(rs)) + .thenCompose(processPageAndAdvance(action)); + } + + public Function, CompletableFuture> processEachAndAdvance( + Consumer> action) { + return processAndAdvanceFunc(rs -> rs.forEach(action)); + } + + public Function, CompletableFuture> processPageAndAdvance( + Consumer>> action) { + return processAndAdvanceFunc(rs -> action.accept(rs.items())); + } + + public Function, CompletableFuture> processAndAdvanceFunc( + Consumer> action) { + return rs -> { + // Empty result set means there were no more objects to fetch. + if (rs.isEmpty()) { + return CompletableFuture.completedFuture(null); + } + + // Apply provided callback for each method -- consume current page. + action.accept(rs); + + // Advance iteration. + return rs.fetchNextPage().thenCompose(processAndAdvanceFunc(action)); + }; + } + + public static AsyncPaginator of(WeaviateQueryClientAsync query) { + return of(query, ObjectBuilder.identity()); + } + + public static AsyncPaginator of(WeaviateQueryClientAsync query, + Function, ObjectBuilder>> fn) { + return fn.apply(new Builder<>(query)).build(); + } + + public static class Builder implements ObjectBuilder> { + private final WeaviateQueryClientAsync query; + + private Function> queryOptions = ObjectBuilder.identity(); + private int pageSize = Paginator.DEFAULT_PAGE_SIZE; + private String cursor; + private boolean prefetch = false; + + public Builder(WeaviateQueryClientAsync query) { + this.query = query; + } + + // Pagination options ----------------------------------------------------- + + public Builder pageSize(int pageSize) { + this.pageSize = pageSize; + return this; + } + + public Builder resumeFrom(String uuid) { + this.cursor = uuid; + return this; + } + + public Builder prefetch(boolean enable) { + this.prefetch = enable; + return this; + } + + // Query options ---------------------------------------------------------- + + public final Builder returnProperties(String... properties) { + return applyQueryOption(q -> q.returnProperties(properties)); + } + + public final Builder returnProperties(List properties) { + return applyQueryOption(q -> q.returnProperties(properties)); + } + + public final Builder returnReferences(QueryReference... references) { + return applyQueryOption(q -> q.returnReferences(references)); + } + + public final Builder returnReferences(List references) { + return applyQueryOption(q -> q.returnReferences(references)); + } + + public final Builder returnMetadata(Metadata... metadata) { + return applyQueryOption(q -> q.returnMetadata(metadata)); + } + + public final Builder returnMetadata(List metadata) { + return applyQueryOption(q -> q.returnMetadata(metadata)); + } + + private final Builder applyQueryOption(Function options) { + this.queryOptions = ObjectBuilder.partial(this.queryOptions, options); + return this; + } + + @Override + public AsyncPaginator build() { + return new AsyncPaginator<>(this); + } + } +} diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/CursorSpliterator.java b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/CursorSpliterator.java new file mode 100644 index 000000000..6d474c16a --- /dev/null +++ b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/CursorSpliterator.java @@ -0,0 +1,64 @@ +package io.weaviate.client6.v1.api.collections.pagination; + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Spliterator; +import java.util.function.BiFunction; +import java.util.function.Consumer; + +import io.weaviate.client6.v1.api.collections.WeaviateObject; +import io.weaviate.client6.v1.api.collections.query.QueryMetadata; + +public class CursorSpliterator implements Spliterator> { + private final int pageSize; + private final BiFunction>> fetch; + + // Spliterators do not promise thread-safety, so there's no mechanism + // to protect access to its internal state. + private String cursor; + private Iterator> currentPage = Collections.emptyIterator(); + + public CursorSpliterator(String cursor, int pageSize, + BiFunction>> fetch) { + this.cursor = cursor; + this.pageSize = pageSize; + this.fetch = fetch; + } + + @Override + public boolean tryAdvance(Consumer> action) { + // Happy path: there are remaining objects in the current page. + if (currentPage.hasNext()) { + action.accept(currentPage.next()); + return true; + } + + // It's OK for the cursor to be null, because it's String (object). + var nextPage = fetch.apply(cursor, pageSize); + if (nextPage.isEmpty()) { + return false; + } + cursor = nextPage.get(nextPage.size() - 1).metadata().uuid(); + currentPage = nextPage.iterator(); + return tryAdvance(action); + } + + @Override + public Spliterator> trySplit() { + // Do not support splitting just now; + return null; + } + + @Override + public long estimateSize() { + // CursorSpliterator does not have SIZED characteristic, so this is our + // best-effort estimate. The number of objects in the db is unbounded. + return Long.MAX_VALUE; + } + + @Override + public int characteristics() { + return ORDERED | DISTINCT | NONNULL; + } +} diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/Paginator.java b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/Paginator.java new file mode 100644 index 000000000..213448e34 --- /dev/null +++ b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/Paginator.java @@ -0,0 +1,119 @@ +package io.weaviate.client6.v1.api.collections.pagination; + +import java.util.Iterator; +import java.util.List; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.function.Function; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +import io.weaviate.client6.v1.api.collections.WeaviateObject; +import io.weaviate.client6.v1.api.collections.query.FetchObjects; +import io.weaviate.client6.v1.api.collections.query.Metadata; +import io.weaviate.client6.v1.api.collections.query.QueryMetadata; +import io.weaviate.client6.v1.api.collections.query.QueryReference; +import io.weaviate.client6.v1.api.collections.query.WeaviateQueryClient; +import io.weaviate.client6.v1.internal.ObjectBuilder; + +public class Paginator implements Iterable> { + static final int DEFAULT_PAGE_SIZE = 100; + + private final WeaviateQueryClient query; + private final Function> queryOptions; + private final int pageSize; + private final String cursor; + + @Override + public Iterator> iterator() { + return Spliterators.iterator(spliterator()); + } + + public Stream> stream() { + return StreamSupport.stream(spliterator(), false); + } + + public Spliterator> spliterator() { + return new CursorSpliterator(cursor, pageSize, + (after, limit) -> { + var fn = ObjectBuilder.partial(queryOptions, q -> q.after(after).limit(limit)); + return query.fetchObjects(fn).objects(); + }); + } + + public static Paginator of(WeaviateQueryClient query) { + return of(query, ObjectBuilder.identity()); + } + + public static Paginator of(WeaviateQueryClient query, + Function, ObjectBuilder>> fn) { + return fn.apply(new Builder<>(query)).build(); + } + + Paginator(Builder builder) { + this.query = builder.query; + this.queryOptions = builder.queryOptions; + this.cursor = builder.cursor; + this.pageSize = builder.pageSize; + } + + public static class Builder implements ObjectBuilder> { + private final WeaviateQueryClient query; + + private Function> queryOptions = ObjectBuilder.identity(); + private int pageSize = DEFAULT_PAGE_SIZE; + private String cursor; + + public Builder(WeaviateQueryClient query) { + this.query = query; + } + + // Pagination options ----------------------------------------------------- + + public Builder pageSize(int pageSize) { + this.pageSize = pageSize; + return this; + } + + public Builder resumeFrom(String uuid) { + this.cursor = uuid; + return this; + } + + // Query options ---------------------------------------------------------- + + public final Builder returnProperties(String... properties) { + return applyQueryOption(q -> q.returnProperties(properties)); + } + + public final Builder returnProperties(List properties) { + return applyQueryOption(q -> q.returnProperties(properties)); + } + + public final Builder returnReferences(QueryReference... references) { + return applyQueryOption(q -> q.returnReferences(references)); + } + + public final Builder returnReferences(List references) { + return applyQueryOption(q -> q.returnReferences(references)); + } + + public final Builder returnMetadata(Metadata... metadata) { + return applyQueryOption(q -> q.returnMetadata(metadata)); + } + + public final Builder returnMetadata(List metadata) { + return applyQueryOption(q -> q.returnMetadata(metadata)); + } + + private final Builder applyQueryOption(Function options) { + this.queryOptions = ObjectBuilder.partial(this.queryOptions, options); + return this; + } + + @Override + public Paginator build() { + return new Paginator<>(this); + } + } +} diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/BaseQueryOptions.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/BaseQueryOptions.java index bcf4bd59d..3a2815864 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/BaseQueryOptions.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/BaseQueryOptions.java @@ -86,17 +86,29 @@ public final SELF where(Where where) { } public final SELF returnProperties(String... properties) { - this.returnProperties = Arrays.asList(properties); + return returnProperties(Arrays.asList(properties)); + } + + public final SELF returnProperties(List properties) { + this.returnProperties.addAll(properties); return (SELF) this; } public final SELF returnReferences(QueryReference... references) { - this.returnReferences = Arrays.asList(references); + return returnReferences(Arrays.asList(references)); + } + + public final SELF returnReferences(List references) { + this.returnReferences.addAll(references); return (SELF) this; } public final SELF returnMetadata(Metadata... metadata) { - this.returnMetadata = Arrays.asList(metadata); + return returnMetadata(Arrays.asList(metadata)); + } + + public final SELF returnMetadata(List metadata) { + this.returnMetadata.addAll(metadata); return (SELF) this; } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/Where.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/Where.java index 0542db68e..09c460acb 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/Where.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/Where.java @@ -217,14 +217,6 @@ public Where lt(String... values) { return new Where(Operator.LESS_THAN, left, new TextArrayOperand(values)); } - public Where lt(Boolean value) { - return new Where(Operator.LESS_THAN, left, new BooleanOperand(value)); - } - - public Where lt(Boolean... values) { - return new Where(Operator.LESS_THAN, left, new BooleanArrayOperand(values)); - } - public Where lt(Integer value) { return new Where(Operator.LESS_THAN, left, new IntegerOperand(value)); } @@ -263,14 +255,6 @@ public Where lte(String... values) { return new Where(Operator.LESS_THAN_EQUAL, left, new TextArrayOperand(values)); } - public Where lte(Boolean value) { - return new Where(Operator.LESS_THAN_EQUAL, left, new BooleanOperand(value)); - } - - public Where lte(Boolean... values) { - return new Where(Operator.LESS_THAN_EQUAL, left, new BooleanArrayOperand(values)); - } - public Where lte(Integer value) { return new Where(Operator.LESS_THAN_EQUAL, left, new IntegerOperand(value)); } @@ -309,14 +293,6 @@ public Where gt(String... values) { return new Where(Operator.GREATER_THAN, left, new TextArrayOperand(values)); } - public Where gt(Boolean value) { - return new Where(Operator.GREATER_THAN, left, new BooleanOperand(value)); - } - - public Where gt(Boolean... values) { - return new Where(Operator.GREATER_THAN, left, new BooleanArrayOperand(values)); - } - public Where gt(Integer value) { return new Where(Operator.GREATER_THAN, left, new IntegerOperand(value)); } @@ -355,14 +331,6 @@ public Where gte(String... values) { return new Where(Operator.GREATER_THAN_EQUAL, left, new TextArrayOperand(values)); } - public Where gte(Boolean value) { - return new Where(Operator.GREATER_THAN_EQUAL, left, new BooleanOperand(value)); - } - - public Where gte(Boolean... values) { - return new Where(Operator.GREATER_THAN_EQUAL, left, new BooleanArrayOperand(values)); - } - public Where gte(Integer value) { return new Where(Operator.GREATER_THAN_EQUAL, left, new IntegerOperand(value)); } @@ -397,46 +365,6 @@ public Where like(String value) { return new Where(Operator.LIKE, left, new TextOperand(value)); } - public Where like(String... values) { - return new Where(Operator.LIKE, left, new TextArrayOperand(values)); - } - - public Where like(Boolean value) { - return new Where(Operator.LIKE, left, new BooleanOperand(value)); - } - - public Where like(Boolean... values) { - return new Where(Operator.LIKE, left, new BooleanArrayOperand(values)); - } - - public Where like(Integer value) { - return new Where(Operator.LIKE, left, new IntegerOperand(value)); - } - - public Where like(Integer... values) { - return new Where(Operator.LIKE, left, new IntegerArrayOperand(values)); - } - - public Where like(Number value) { - return new Where(Operator.LIKE, left, new NumberOperand(value.doubleValue())); - } - - public Where like(Number... values) { - return new Where(Operator.LIKE, left, new NumberArrayOperand(values)); - } - - public Where like(Date value) { - return new Where(Operator.LIKE, left, new DateOperand(value)); - } - - public Where like(Date... values) { - return new Where(Operator.LIKE, left, new DateArrayOperand(values)); - } - - public Where like(Object value) { - return new Where(Operator.LIKE, left, fromObject(value)); - } - // ContainsAny // ------------------------------------------------------------------------ public Where containsAny(String value) { diff --git a/src/main/java/io/weaviate/client6/v1/internal/ObjectBuilder.java b/src/main/java/io/weaviate/client6/v1/internal/ObjectBuilder.java index 9d6ffe567..550b4266d 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/ObjectBuilder.java +++ b/src/main/java/io/weaviate/client6/v1/internal/ObjectBuilder.java @@ -8,4 +8,9 @@ public interface ObjectBuilder { static , T> Function> identity() { return builder -> builder; } + + static , T> Function> partial(Function> fn, + Function partialFn) { + return partialFn.andThen(fn); + } }