diff --git a/README.md b/README.md index 817b21d78..6db7b39e9 100644 --- a/README.md +++ b/README.md @@ -430,8 +430,8 @@ songs.query.hybrid( Objects can be filtered by property or reference values. In the latter case you need to pass the "path" to the property in the referenced collection. ```java -.where(Where.property("year").gte(1969)) -.where(Where.reference("hasAwards", "GrammyAwards", "category").eq("New Artist")) +.filters(Filter.property("year").gte(1969)) +.filters(Filter.reference("hasAwards", "GrammyAwards", "category").eq("New Artist")) ``` Supported **comparison operators**: @@ -451,15 +451,15 @@ Supported **comparison operators**: Comparison operators can be grouped using **logical operators** with arbitrarily deep nesting. ```java -.where( - Where.or( - Where.and( - Where.property("year").gt(2000), - Where.property("year").lt(2017) +.filters( + Filter.or( + Filter.and( + Filter.property("year").gt(2000), + Filter.property("year").lt(2017) ), - Where.or( - Where.property("artist").like("Boys"), - Where.property("genres").containsAny("#rock", "#rocknroll", "#grunge") + Filter.or( + Filter.property("artist").like("Boys"), + Filter.property("genres").containsAny("#rock", "#rocknroll", "#grunge") ) ) ) @@ -471,23 +471,23 @@ Supported **logical operators**: - Or: `.or` - Not: `.not` -Operators passed in subsequent calls to `.where` are concatenated with the `.and` operartor. +Operators passed in subsequent calls to `.filters` are concatenated with the `.and` operartor. These 3 calls are equivalent: ```java -.where(Where.and(cond1, cond2)) -.where(cond1, cond2) -.where(cond1).where(cond2) +.filters(Filter.and(cond1, cond2)) +.filters(cond1, cond2) +.filters(cond1).filters(cond2) ``` -To negate an operator, wrap it in `Where.not(...)` or use the negation shorthand. +To negate an operator, wrap it in `Filter.not(...)` or use the negation shorthand. ```java -Where.not(Where.property("title").like("summer")); -Where.property("title").like("summer").not(); +Filter.not(Filter.property("title").like("summer")); +Filter.property("title").like("summer").not(); ``` -Passing `null` and and empty `Where[]` to any of the logical operators as well as to the `.where()` method is safe -- the empty operators will simply be ignored. +Passing `null` and empty `Filter[]` to any of the logical operators as well as to the `.filters()` method is safe -- the empty operators will simply be ignored. #### Grouping results diff --git a/src/it/java/io/weaviate/integration/DataITest.java b/src/it/java/io/weaviate/integration/DataITest.java index 598053904..ddd34b391 100644 --- a/src/it/java/io/weaviate/integration/DataITest.java +++ b/src/it/java/io/weaviate/integration/DataITest.java @@ -28,7 +28,7 @@ import io.weaviate.client6.v1.api.collections.query.Metadata.MetadataField; import io.weaviate.client6.v1.api.collections.query.QueryMetadata; import io.weaviate.client6.v1.api.collections.query.QueryReference; -import io.weaviate.client6.v1.api.collections.query.Where; +import io.weaviate.client6.v1.api.collections.query.Filter; import io.weaviate.containers.Container; public class DataITest extends ConcurrentTest { @@ -303,7 +303,7 @@ public void testDeleteMany() throws IOException { // Act (dry run) things.data.deleteMany( - Where.property("last_used").gte(4), + Filter.property("last_used").gte(4), opt -> opt.dryRun(true)); // Assert @@ -312,7 +312,7 @@ public void testDeleteMany() throws IOException { // Act (live run) var deleted = things.data.deleteMany( - Where.property("last_used").gte(4), + Filter.property("last_used").gte(4), opt -> opt.verbose(true)); // Assert diff --git a/src/it/java/io/weaviate/integration/ORMITest.java b/src/it/java/io/weaviate/integration/ORMITest.java index 73b856ea1..6095d91b4 100644 --- a/src/it/java/io/weaviate/integration/ORMITest.java +++ b/src/it/java/io/weaviate/integration/ORMITest.java @@ -21,7 +21,7 @@ import io.weaviate.client6.v1.api.collections.annotations.Collection; import io.weaviate.client6.v1.api.collections.annotations.Property; import io.weaviate.client6.v1.api.collections.data.InsertManyResponse.InsertObject; -import io.weaviate.client6.v1.api.collections.query.Where; +import io.weaviate.client6.v1.api.collections.query.Filter; import io.weaviate.containers.Container; public class ORMITest extends ConcurrentTest { @@ -318,7 +318,7 @@ public void test_insertManyAndQuery() throws Exception { // Assert var uuids = inserted.responses().stream().map(InsertObject::uuid).toArray(String[]::new); - var got = things.query.fetchObjects(q -> q.where(Where.uuid().containsAny(uuids))); + var got = things.query.fetchObjects(q -> q.filters(Filter.uuid().containsAny(uuids))); Assertions.assertThat(got.objects()) .hasSize(3) .usingRecursiveComparison(COMPARISON_CONFIG) diff --git a/src/it/java/io/weaviate/integration/SearchITest.java b/src/it/java/io/weaviate/integration/SearchITest.java index bf31da44f..32c86c493 100644 --- a/src/it/java/io/weaviate/integration/SearchITest.java +++ b/src/it/java/io/weaviate/integration/SearchITest.java @@ -36,7 +36,7 @@ import io.weaviate.client6.v1.api.collections.query.QueryResponseGroup; import io.weaviate.client6.v1.api.collections.query.SortBy; import io.weaviate.client6.v1.api.collections.query.Target; -import io.weaviate.client6.v1.api.collections.query.Where; +import io.weaviate.client6.v1.api.collections.query.Filter; import io.weaviate.client6.v1.api.collections.vectorindex.Hnsw; import io.weaviate.client6.v1.api.collections.vectorindex.MultiVector; import io.weaviate.containers.Container; @@ -251,12 +251,12 @@ public void testFetchObjectsWithFilters() throws IOException { var hugeHat = hats.data.insert(Map.of("colour", "orange", "size", 40)); var got = hats.query.fetchObjects( - query -> query.where( - Where.or( - Where.property("colour").eq("orange"), - Where.and( - Where.property("size").gte(1), - Where.property("size").lt(6))))); + query -> query.filters( + Filter.or( + Filter.property("colour").eq("orange"), + Filter.and( + Filter.property("size").gte(1), + Filter.property("size").lt(6))))); Assertions.assertThat(got.objects()) .extracting(hat -> hat.metadata().uuid()) 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 4698157ab..1e71855d0 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 @@ -3,7 +3,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.api.collections.query.Filter; import io.weaviate.client6.v1.internal.ObjectBuilder; import io.weaviate.client6.v1.internal.grpc.ByteStringUtil; import io.weaviate.client6.v1.internal.grpc.Rpc; @@ -13,7 +13,7 @@ import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBatchDelete; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; -public record DeleteManyRequest(Where where, Boolean verbose, Boolean dryRun) { +public record DeleteManyRequest(Filter filters, Boolean verbose, Boolean dryRun) { public static Rpc rpc( CollectionDescriptor collection, @@ -37,7 +37,7 @@ public static Rpc WeaviateFutureStub::batchDelete); } - public static DeleteManyRequest of(Where where) { - return of(where, ObjectBuilder.identity()); + public static DeleteManyRequest of(Filter filters) { + return of(filters, ObjectBuilder.identity()); } public DeleteManyRequest(Builder builder) { this( - builder.where, + builder.filters, builder.verbose, builder.dryRun); } - public static DeleteManyRequest of(Where where, Function> fn) { - return fn.apply(new Builder(where)).build(); + public static DeleteManyRequest of(Filter filters, Function> fn) { + return fn.apply(new Builder(filters)).build(); } public static class Builder implements ObjectBuilder { // Required request parameters; - private final Where where; + private final Filter filters; private Boolean verbose; private Boolean dryRun; - public Builder(Where where) { - this.where = where; + public Builder(Filter filters) { + this.filters = filters; } public Builder verbose(boolean verbose) { 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 1effe1aa0..caa55a825 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 @@ -9,8 +9,8 @@ import io.weaviate.client6.v1.api.collections.ObjectMetadata; import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.api.collections.query.WeaviateQueryClient; -import io.weaviate.client6.v1.api.collections.query.Where; -import io.weaviate.client6.v1.api.collections.query.WhereOperand; +import io.weaviate.client6.v1.api.collections.query.Filter; +import io.weaviate.client6.v1.api.collections.query.FilterOperand; import io.weaviate.client6.v1.internal.ObjectBuilder; import io.weaviate.client6.v1.internal.grpc.GrpcTransport; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; @@ -104,18 +104,18 @@ public void delete(String uuid) throws IOException { public DeleteManyResponse deleteMany(String... uuids) { var either = Arrays.stream(uuids) - .map(uuid -> (WhereOperand) Where.uuid().eq(uuid)) + .map(uuid -> (FilterOperand) Filter.uuid().eq(uuid)) .toList(); - return deleteMany(DeleteManyRequest.of(Where.or(either))); + return deleteMany(DeleteManyRequest.of(Filter.or(either))); } - public DeleteManyResponse deleteMany(Where where) { - return deleteMany(DeleteManyRequest.of(where)); + public DeleteManyResponse deleteMany(Filter filters) { + return deleteMany(DeleteManyRequest.of(filters)); } - public DeleteManyResponse deleteMany(Where where, + public DeleteManyResponse deleteMany(Filter filters, Function> fn) { - return deleteMany(DeleteManyRequest.of(where, fn)); + return deleteMany(DeleteManyRequest.of(filters, fn)); } public DeleteManyResponse deleteMany(DeleteManyRequest request) { 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 251b2c055..8b47d572d 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 @@ -11,8 +11,8 @@ import io.weaviate.client6.v1.api.collections.ObjectMetadata; import io.weaviate.client6.v1.api.collections.WeaviateObject; import io.weaviate.client6.v1.api.collections.query.WeaviateQueryClientAsync; -import io.weaviate.client6.v1.api.collections.query.Where; -import io.weaviate.client6.v1.api.collections.query.WhereOperand; +import io.weaviate.client6.v1.api.collections.query.Filter; +import io.weaviate.client6.v1.api.collections.query.FilterOperand; import io.weaviate.client6.v1.internal.ObjectBuilder; import io.weaviate.client6.v1.internal.grpc.GrpcTransport; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; @@ -99,18 +99,18 @@ public CompletableFuture delete(String uuid) { public CompletableFuture deleteMany(String... uuids) { var either = Arrays.stream(uuids) - .map(uuid -> (WhereOperand) Where.uuid().eq(uuid)) + .map(uuid -> (FilterOperand) Filter.uuid().eq(uuid)) .toList(); - return deleteMany(DeleteManyRequest.of(Where.or(either))); + return deleteMany(DeleteManyRequest.of(Filter.or(either))); } - public CompletableFuture deleteMany(Where where) { - return deleteMany(DeleteManyRequest.of(where)); + public CompletableFuture deleteMany(Filter filters) { + return deleteMany(DeleteManyRequest.of(filters)); } - public CompletableFuture deleteMany(Where where, + public CompletableFuture deleteMany(Filter filters, Function> fn) { - return deleteMany(DeleteManyRequest.of(where, fn)); + return deleteMany(DeleteManyRequest.of(filters, fn)); } public CompletableFuture deleteMany(DeleteManyRequest request) { diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/Paginator.java b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/Paginator.java index b5de3a370..0d4d53413 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/pagination/Paginator.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/pagination/Paginator.java @@ -14,7 +14,7 @@ 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.api.collections.query.Where; +import io.weaviate.client6.v1.api.collections.query.Filter; import io.weaviate.client6.v1.internal.ObjectBuilder; public class Paginator implements Iterable> { @@ -90,8 +90,8 @@ public Builder fromCursor(String uuid) { // Query options ---------------------------------------------------------- /** Combine several conditions using with an AND operator. */ - public final Builder where(Where... where) { - return applyQueryOption(q -> q.where(where)); + public final Builder filters(Filter... filters) { + return applyQueryOption(q -> q.filters(filters)); } public final Builder returnProperties(String... properties) { 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 bdd3ed82e..64276e425 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 @@ -19,7 +19,7 @@ public record BaseQueryOptions( Integer autolimit, String after, ConsistencyLevel consistencyLevel, - Where where, + Filter filters, GenerativeSearch generativeSearch, List returnProperties, List returnReferences, @@ -33,7 +33,7 @@ private BaseQueryOptions(Builder, T> builder.autolimit, builder.after, builder.consistencyLevel, - builder.where, + builder.filter, builder.generativeSearch, builder.returnProperties, builder.returnReferences, @@ -49,7 +49,7 @@ public static abstract class Builder, T extends private Integer autolimit; private String after; private ConsistencyLevel consistencyLevel; - private Where where; + private Filter filter; private GenerativeSearch generativeSearch; private List returnProperties = new ArrayList<>(); private List returnReferences = new ArrayList<>(); @@ -124,16 +124,16 @@ protected SelfT generate(Function operands; + + @SafeVarargs + private Filter(Operator operator, FilterOperand... operands) { + this(operator, Arrays.asList(operands)); + } + + private Filter(Operator operator, List operands) { + this.operator = operator; + this.operands = operands; + } + + @Override + public boolean isEmpty() { + // Guard against Filter.and(Filter.or(), Filter.and(), Filter.not()) situation. + return operands.isEmpty() + || operands.stream().allMatch(operator -> operator == null | operator.isEmpty()); + } + + @Override + public String toString() { + if (operator == Operator.NOT) { + return "%s %s".formatted(operator, operands.get(0)); + } + var operandStrings = operands.stream().map(Object::toString).toList(); + return "Filter(" + String.join(" " + operator.toString() + " ", operandStrings) + ")"; + } + + // Logical operators return a complete operand. + // -------------------------------------------------------------------------- + public static Filter and(final FilterOperand... operands) { + return new Filter(Operator.AND, operands); + } + + public static Filter and(final List operands) { + return new Filter(Operator.AND, operands); + } + + public static Filter or(final FilterOperand... operands) { + return new Filter(Operator.OR, operands); + } + + public static Filter or(final List operands) { + return new Filter(Operator.OR, operands); + } + + public static Filter not(final FilterOperand operand) { + return new Filter(Operator.NOT, operand); + } + + /** Negate this expression. */ + public Filter not() { + return not(this); + } + + // Comparison operators return fluid builder. + // -------------------------------------------------------------------------- + + /** Filter by object UUID. */ + public static FilterBuilder uuid() { + return property(FetchObjectById.ID_PROPERTY); + } + + /** Filter by object property. */ + public static FilterBuilder property(String property) { + return new FilterBuilder(new PathOperand(property)); + } + + /** Filter by a property of the referenced object. */ + public static FilterBuilder reference(String... path) { + return new FilterBuilder(new PathOperand(path)); + } + + public static class FilterBuilder { + private final FilterOperand left; + + private FilterBuilder(FilterOperand left) { + this.left = left; + } + + // Equal + // ------------------------------------------------------------------------ + public Filter eq(String value) { + return new Filter(Operator.EQUAL, left, new TextOperand(value)); + } + + public Filter eq(String... values) { + return new Filter(Operator.EQUAL, left, new TextArrayOperand(values)); + } + + public Filter eq(boolean value) { + return new Filter(Operator.EQUAL, left, new BooleanOperand(value)); + } + + public Filter eq(Boolean... values) { + return new Filter(Operator.EQUAL, left, new BooleanArrayOperand(values)); + } + + public Filter eq(long value) { + return new Filter(Operator.EQUAL, left, new IntegerOperand(value)); + } + + public Filter eq(int value) { + return new Filter(Operator.EQUAL, left, new IntegerOperand(value)); + } + + public Filter eq(Long... values) { + return new Filter(Operator.EQUAL, left, new IntegerArrayOperand(values)); + } + + public Filter eq(double value) { + return new Filter(Operator.EQUAL, left, new NumberOperand(value)); + } + + public Filter eq(float value) { + return new Filter(Operator.EQUAL, left, new NumberOperand(value)); + } + + public Filter eq(Double... values) { + return new Filter(Operator.EQUAL, left, new NumberArrayOperand(values)); + } + + public Filter eq(OffsetDateTime value) { + return new Filter(Operator.EQUAL, left, new DateOperand(value)); + } + + public Filter eq(OffsetDateTime... values) { + return new Filter(Operator.EQUAL, left, new DateArrayOperand(values)); + } + + public Filter eq(Object value) { + return new Filter(Operator.EQUAL, left, fromObject(value)); + } + + // NotEqual + // ------------------------------------------------------------------------ + public Filter ne(String value) { + return new Filter(Operator.NOT_EQUAL, left, new TextOperand(value)); + } + + public Filter ne(String... values) { + return new Filter(Operator.NOT_EQUAL, left, new TextArrayOperand(values)); + } + + public Filter ne(boolean value) { + return new Filter(Operator.NOT_EQUAL, left, new BooleanOperand(value)); + } + + public Filter ne(Boolean... values) { + return new Filter(Operator.NOT_EQUAL, left, new BooleanArrayOperand(values)); + } + + public Filter ne(long value) { + return new Filter(Operator.NOT_EQUAL, left, new IntegerOperand(value)); + } + + public Filter ne(int value) { + return new Filter(Operator.NOT_EQUAL, left, new IntegerOperand(value)); + } + + public Filter ne(Long... values) { + return new Filter(Operator.NOT_EQUAL, left, new IntegerArrayOperand(values)); + } + + public Filter ne(double value) { + return new Filter(Operator.NOT_EQUAL, left, new NumberOperand(value)); + } + + public Filter ne(float value) { + return new Filter(Operator.NOT_EQUAL, left, new NumberOperand(value)); + } + + public Filter ne(Double... values) { + return new Filter(Operator.NOT_EQUAL, left, new NumberArrayOperand(values)); + } + + public Filter ne(OffsetDateTime value) { + return new Filter(Operator.NOT_EQUAL, left, new DateOperand(value)); + } + + public Filter ne(OffsetDateTime... values) { + return new Filter(Operator.NOT_EQUAL, left, new DateArrayOperand(values)); + } + + public Filter ne(Object value) { + return new Filter(Operator.NOT_EQUAL, left, fromObject(value)); + } + + // LessThan + // ------------------------------------------------------------------------ + public Filter lt(String value) { + return new Filter(Operator.LESS_THAN, left, new TextOperand(value)); + } + + public Filter lt(String... values) { + return new Filter(Operator.LESS_THAN, left, new TextArrayOperand(values)); + } + + public Filter lt(long value) { + return new Filter(Operator.LESS_THAN, left, new IntegerOperand(value)); + } + + public Filter lt(int value) { + return new Filter(Operator.LESS_THAN, left, new IntegerOperand(value)); + } + + public Filter lt(Long... values) { + return new Filter(Operator.LESS_THAN, left, new IntegerArrayOperand(values)); + } + + public Filter lt(double value) { + return new Filter(Operator.LESS_THAN, left, new NumberOperand(value)); + } + + public Filter lt(float value) { + return new Filter(Operator.LESS_THAN, left, new NumberOperand(value)); + } + + public Filter lt(Double... values) { + return new Filter(Operator.LESS_THAN, left, new NumberArrayOperand(values)); + } + + public Filter lt(OffsetDateTime value) { + return new Filter(Operator.LESS_THAN, left, new DateOperand(value)); + } + + public Filter lt(OffsetDateTime... values) { + return new Filter(Operator.LESS_THAN, left, new DateArrayOperand(values)); + } + + public Filter lt(Object value) { + return new Filter(Operator.LESS_THAN, left, fromObject(value)); + } + + // LessThanEqual + // ------------------------------------------------------------------------ + public Filter lte(String value) { + return new Filter(Operator.LESS_THAN_EQUAL, left, new TextOperand(value)); + } + + public Filter lte(String... values) { + return new Filter(Operator.LESS_THAN_EQUAL, left, new TextArrayOperand(values)); + } + + public Filter lte(long value) { + return new Filter(Operator.LESS_THAN_EQUAL, left, new IntegerOperand(value)); + } + + public Filter lte(int value) { + return new Filter(Operator.LESS_THAN_EQUAL, left, new IntegerOperand(value)); + } + + public Filter lte(Long... values) { + return new Filter(Operator.LESS_THAN_EQUAL, left, new IntegerArrayOperand(values)); + } + + public Filter lte(double value) { + return new Filter(Operator.LESS_THAN_EQUAL, left, new NumberOperand(value)); + } + + public Filter lte(float value) { + return new Filter(Operator.LESS_THAN_EQUAL, left, new NumberOperand(value)); + } + + public Filter lte(Double... values) { + return new Filter(Operator.LESS_THAN_EQUAL, left, new NumberArrayOperand(values)); + } + + public Filter lte(OffsetDateTime value) { + return new Filter(Operator.LESS_THAN_EQUAL, left, new DateOperand(value)); + } + + public Filter lte(OffsetDateTime... values) { + return new Filter(Operator.LESS_THAN_EQUAL, left, new DateArrayOperand(values)); + } + + public Filter lte(Object value) { + return new Filter(Operator.LESS_THAN_EQUAL, left, fromObject(value)); + } + + // GreaterThan + // ------------------------------------------------------------------------ + public Filter gt(String value) { + return new Filter(Operator.GREATER_THAN, left, new TextOperand(value)); + } + + public Filter gt(String... values) { + return new Filter(Operator.GREATER_THAN, left, new TextArrayOperand(values)); + } + + public Filter gt(long value) { + return new Filter(Operator.GREATER_THAN, left, new IntegerOperand(value)); + } + + public Filter gt(int value) { + return new Filter(Operator.GREATER_THAN, left, new IntegerOperand(value)); + } + + public Filter gt(Long... values) { + return new Filter(Operator.GREATER_THAN, left, new IntegerArrayOperand(values)); + } + + public Filter gt(double value) { + return new Filter(Operator.GREATER_THAN, left, new NumberOperand(value)); + } + + public Filter gt(float value) { + return new Filter(Operator.GREATER_THAN, left, new NumberOperand(value)); + } + + public Filter gt(Double... values) { + return new Filter(Operator.GREATER_THAN, left, new NumberArrayOperand(values)); + } + + public Filter gt(OffsetDateTime value) { + return new Filter(Operator.GREATER_THAN, left, new DateOperand(value)); + } + + public Filter gt(OffsetDateTime... values) { + return new Filter(Operator.GREATER_THAN, left, new DateArrayOperand(values)); + } + + public Filter gt(Object value) { + return new Filter(Operator.GREATER_THAN, left, fromObject(value)); + } + + // GreaterThanEqual + // ------------------------------------------------------------------------ + public Filter gte(String value) { + return new Filter(Operator.GREATER_THAN_EQUAL, left, new TextOperand(value)); + } + + public Filter gte(String... values) { + return new Filter(Operator.GREATER_THAN_EQUAL, left, new TextArrayOperand(values)); + } + + public Filter gte(long value) { + return new Filter(Operator.GREATER_THAN_EQUAL, left, new IntegerOperand(value)); + } + + public Filter gte(int value) { + return new Filter(Operator.GREATER_THAN_EQUAL, left, new IntegerOperand(value)); + } + + public Filter gte(Long... values) { + return new Filter(Operator.GREATER_THAN_EQUAL, left, new IntegerArrayOperand(values)); + } + + public Filter gte(double value) { + return new Filter(Operator.GREATER_THAN_EQUAL, left, new NumberOperand(value)); + } + + public Filter gte(float value) { + return new Filter(Operator.GREATER_THAN_EQUAL, left, new NumberOperand(value)); + } + + public Filter gte(Double... values) { + return new Filter(Operator.GREATER_THAN_EQUAL, left, new NumberArrayOperand(values)); + } + + public Filter gte(OffsetDateTime value) { + return new Filter(Operator.GREATER_THAN_EQUAL, left, new DateOperand(value)); + } + + public Filter gte(OffsetDateTime... values) { + return new Filter(Operator.GREATER_THAN_EQUAL, left, new DateArrayOperand(values)); + } + + public Filter gte(Object value) { + return new Filter(Operator.GREATER_THAN_EQUAL, left, fromObject(value)); + } + + // Like + // ------------------------------------------------------------------------ + public Filter like(String value) { + return new Filter(Operator.LIKE, left, new TextOperand(value)); + } + + // ContainsAny + // ------------------------------------------------------------------------ + public Filter containsAny(String value) { + return new Filter(Operator.CONTAINS_ANY, left, new TextOperand(value)); + } + + public Filter containsAny(String... values) { + return new Filter(Operator.CONTAINS_ANY, left, new TextArrayOperand(values)); + } + + public Filter containsAny(List values) { + return new Filter(Operator.CONTAINS_ANY, left, new TextArrayOperand(values)); + } + + public Filter containsAny(Boolean... values) { + return new Filter(Operator.CONTAINS_ANY, left, new BooleanArrayOperand(values)); + } + + public Filter containsAny(Long... values) { + return new Filter(Operator.CONTAINS_ANY, left, new IntegerArrayOperand(values)); + } + + public Filter containsAny(Double... values) { + return new Filter(Operator.CONTAINS_ANY, left, new NumberArrayOperand(values)); + } + + public Filter containsAny(OffsetDateTime... values) { + return new Filter(Operator.CONTAINS_ANY, left, new DateArrayOperand(values)); + } + + // ContainsAll + // ------------------------------------------------------------------------ + public Filter containsAll(String value) { + return new Filter(Operator.CONTAINS_ALL, left, new TextOperand(value)); + } + + public Filter containsAll(String... values) { + return new Filter(Operator.CONTAINS_ALL, left, new TextArrayOperand(values)); + } + + public Filter containsAll(List values) { + return new Filter(Operator.CONTAINS_ALL, left, new TextArrayOperand(values)); + } + + public Filter containsAll(Boolean... values) { + return new Filter(Operator.CONTAINS_ALL, left, new BooleanArrayOperand(values)); + } + + public Filter containsAll(Long... values) { + return new Filter(Operator.CONTAINS_ALL, left, new IntegerArrayOperand(values)); + } + + public Filter containsAll(Double... values) { + return new Filter(Operator.CONTAINS_ALL, left, new NumberArrayOperand(values)); + } + + public Filter containsAll(OffsetDateTime... values) { + return new Filter(Operator.CONTAINS_ALL, left, new DateArrayOperand(values)); + } + + // ContainsNone + // ------------------------------------------------------------------------ + public Filter containsNone(String value) { + return new Filter(Operator.CONTAINS_NONE, left, new TextOperand(value)); + } + + public Filter containsNone(String... values) { + return new Filter(Operator.CONTAINS_NONE, left, new TextArrayOperand(values)); + } + + public Filter containsNone(List values) { + return new Filter(Operator.CONTAINS_NONE, left, new TextArrayOperand(values)); + } + + public Filter containsNone(Boolean... values) { + return new Filter(Operator.CONTAINS_NONE, left, new BooleanArrayOperand(values)); + } + + public Filter containsNone(Long... values) { + return new Filter(Operator.CONTAINS_NONE, left, new IntegerArrayOperand(values)); + } + + public Filter containsNone(Double... values) { + return new Filter(Operator.CONTAINS_NONE, left, new NumberArrayOperand(values)); + } + + public Filter containsNone(OffsetDateTime... values) { + return new Filter(Operator.CONTAINS_NONE, left, new DateArrayOperand(values)); + } + + // WithinGeoRange + // ------------------------------------------------------------------------ + public Filter withinGeoRange(float lat, float lon, float maxDistance) { + return new Filter(Operator.WITHIN_GEO_RANGE, left, new GeoRangeOperand(lat, lon, maxDistance)); + } + } + + @Override + public void appendTo(WeaviateProtoBase.Filters.Builder filter) { + if (isEmpty()) { + return; + } + + operator.appendTo(filter); + + if (operator == Operator.AND || operator == Operator.OR || operator == Operator.NOT) { + operands.forEach(op -> { + var nested = Filters.newBuilder(); + op.appendTo(nested); + filter.addFilters(nested); + }); + } else { + // Comparison operators: eq, gt, lt, like, etc. + operands.forEach(op -> op.appendTo(filter)); + } + } + + @SuppressWarnings("unchecked") + static FilterOperand fromObject(Object value) { + if (value instanceof String str) { + return new TextOperand(str); + } else if (value instanceof Boolean bool) { + return new BooleanOperand(bool); + } else if (value instanceof Long l) { + return new IntegerOperand(l); + } else if (value instanceof Integer i) { + return new IntegerOperand(i); + } else if (value instanceof Double dbl) { + return new NumberOperand(dbl); + } else if (value instanceof Float f) { + return new NumberOperand(f); + } else if (value instanceof OffsetDateTime date) { + return new DateOperand(date); + } else if (value instanceof String[] strarr) { + return new TextArrayOperand(strarr); + } else if (value instanceof Boolean[] boolarr) { + return new BooleanArrayOperand(boolarr); + } else if (value instanceof Long[] lngarr) { + return new IntegerArrayOperand(lngarr); + } else if (value instanceof Double[] dblarr) { + return new NumberArrayOperand(dblarr); + } else if (value instanceof OffsetDateTime[] datearr) { + return new DateArrayOperand(datearr); + } else if (value instanceof List list) { + if (list.isEmpty()) { + throw new IllegalArgumentException( + "Filter with non-reifiable type (List) cannot be empty, use an array instead"); + } + + Object first = list.get(0); + if (first instanceof String) { + return new TextArrayOperand((List) value); + } else if (first instanceof Boolean) { + return new BooleanArrayOperand((List) value); + } else if (first instanceof Long) { + return new IntegerArrayOperand((List) value); + } else if (first instanceof Double) { + return new NumberArrayOperand((List) value); + } else if (first instanceof OffsetDateTime) { + return new DateArrayOperand((List) value); + } + } + throw new IllegalArgumentException( + "value must be either of String, Boolean, OffsetDateTime, Long, Double, or Array/List of these types"); + } + + private static class PathOperand implements FilterOperand { + private final List path; + + private PathOperand(List path) { + this.path = path; + } + + private PathOperand(String... path) { + this(Arrays.asList(path)); + } + + @Override + public void appendTo(WeaviateProtoBase.Filters.Builder filter) { + // "on" is deprecated, but the current proto doesn't have "path". + if (!path.isEmpty()) { + filter.addOn(path.get(0)); + } + // FIXME: no way to reference objects rn? + } + + @Override + public String toString() { + return String.join("::", path); + } + } + + private static class TextOperand implements FilterOperand { + private final String value; + + private TextOperand(String value) { + this.value = value; + } + + @Override + public void appendTo(WeaviateProtoBase.Filters.Builder filter) { + filter.setValueText(value); + } + + @Override + public String toString() { + return value; + } + } + + private static class TextArrayOperand implements FilterOperand { + private final List values; + + private TextArrayOperand(List values) { + this.values = values; + } + + @SafeVarargs + private TextArrayOperand(String... values) { + this(Arrays.asList(values)); + } + + @Override + public void appendTo(WeaviateProtoBase.Filters.Builder filter) { + filter.setValueTextArray(WeaviateProtoBase.TextArray.newBuilder().addAllValues(values)); + } + + @Override + public String toString() { + return values.toString(); + } + } + + private static class BooleanOperand implements FilterOperand { + private final boolean value; + + private BooleanOperand(boolean value) { + this.value = value; + } + + @Override + public void appendTo(WeaviateProtoBase.Filters.Builder filter) { + filter.setValueBoolean(value); + } + + @Override + public String toString() { + return Boolean.toString(value); + } + } + + private static class BooleanArrayOperand implements FilterOperand { + private final List values; + + private BooleanArrayOperand(List values) { + this.values = values; + } + + @SafeVarargs + private BooleanArrayOperand(Boolean... values) { + this(Arrays.asList(values)); + } + + @Override + public void appendTo(WeaviateProtoBase.Filters.Builder filter) { + filter.setValueBooleanArray(WeaviateProtoBase.BooleanArray.newBuilder().addAllValues(values)); + } + + @Override + public String toString() { + return values.toString(); + } + } + + private static class IntegerOperand implements FilterOperand { + private final long value; + + private IntegerOperand(long value) { + this.value = value; + } + + private IntegerOperand(int value) { + this.value = value; + } + + @Override + public void appendTo(WeaviateProtoBase.Filters.Builder filter) { + filter.setValueInt(value); + } + + @Override + public String toString() { + return Long.toString(value); + } + } + + private static class IntegerArrayOperand implements FilterOperand { + private final List values; + + private IntegerArrayOperand(List values) { + this.values = values; + } + + @SafeVarargs + private IntegerArrayOperand(Long... values) { + this(Arrays.asList(values)); + } + + @Override + public void appendTo(WeaviateProtoBase.Filters.Builder filter) { + filter.setValueIntArray(WeaviateProtoBase.IntArray.newBuilder().addAllValues(values)); + } + + @Override + public String toString() { + return values.toString(); + } + } + + private static class NumberOperand implements FilterOperand { + private final double value; + + private NumberOperand(double value) { + this.value = value; + } + + private NumberOperand(float value) { + this.value = value; + } + + @Override + public void appendTo(WeaviateProtoBase.Filters.Builder filter) { + filter.setValueNumber(value); + } + + @Override + public String toString() { + return Double.toString(value); + } + } + + private static class NumberArrayOperand implements FilterOperand { + private final List values; + + private NumberArrayOperand(List values) { + this.values = values; + } + + @SafeVarargs + private NumberArrayOperand(Double... values) { + this(Arrays.asList(values)); + } + + @Override + public void appendTo(WeaviateProtoBase.Filters.Builder filter) { + filter.setValueNumberArray(WeaviateProtoBase.NumberArray.newBuilder().addAllValues(values)); + } + + @Override + public String toString() { + return values.toString(); + } + } + + private static class DateOperand implements FilterOperand { + private final OffsetDateTime value; + + private DateOperand(OffsetDateTime value) { + this.value = value; + } + + @Override + public void appendTo(WeaviateProtoBase.Filters.Builder filter) { + filter.setValueText(value.toString()); + } + + @Override + public String toString() { + return value.toString(); + } + } + + private static class DateArrayOperand implements FilterOperand { + private final List values; + + private DateArrayOperand(List values) { + this.values = values; + } + + @SafeVarargs + private DateArrayOperand(OffsetDateTime... values) { + this(Arrays.asList(values)); + } + + private List formatted() { + return values.stream().map(OffsetDateTime::toString).toList(); + } + + @Override + public void appendTo(WeaviateProtoBase.Filters.Builder filter) { + filter.setValueTextArray(WeaviateProtoBase.TextArray.newBuilder().addAllValues(formatted())); + } + + @Override + public String toString() { + return values.toString(); + } + } + + private static class GeoRangeOperand implements FilterOperand { + private final float lat; + private final float lon; + private final float distance; + + private GeoRangeOperand(float lat, float lon, float distance) { + this.lat = lat; + this.lon = lon; + this.distance = distance; + } + + @Override + public void appendTo(WeaviateProtoBase.Filters.Builder filter) { + filter.setValueGeo(WeaviateProtoBase.GeoCoordinatesFilter.newBuilder() + .setLatitude(lat).setLongitude(lon).setDistance(distance)); + } + + @Override + public String toString() { + return "(lat=%d, lon=%d, distance=%d)".formatted(lat, lon, distance); + } + } +} diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/WhereOperand.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/FilterOperand.java similarity index 66% rename from src/main/java/io/weaviate/client6/v1/api/collections/query/WhereOperand.java rename to src/main/java/io/weaviate/client6/v1/api/collections/query/FilterOperand.java index 40b46456a..b7a79683b 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/WhereOperand.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/FilterOperand.java @@ -2,8 +2,8 @@ import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBase; -public interface WhereOperand { - void appendTo(WeaviateProtoBase.Filters.Builder where); +public interface FilterOperand { + void appendTo(WeaviateProtoBase.Filters.Builder filter); default boolean isEmpty() { return false; diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/query/NearObject.java b/src/main/java/io/weaviate/client6/v1/api/collections/query/NearObject.java index 33e389e43..34772d399 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/NearObject.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/query/NearObject.java @@ -32,7 +32,7 @@ public Builder(String uuid) { } public Builder excludeSelf() { - return where(Where.uuid().ne(uuid)); + return filters(Filter.uuid().ne(uuid)); } @Override 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 deleted file mode 100644 index b28f68a2f..000000000 --- a/src/main/java/io/weaviate/client6/v1/api/collections/query/Where.java +++ /dev/null @@ -1,862 +0,0 @@ -package io.weaviate.client6.v1.api.collections.query; - -import java.time.OffsetDateTime; -import java.util.Arrays; -import java.util.List; - -import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBase; -import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBase.Filters; - -public class Where implements WhereOperand { - - private enum Operator { - // Logical operators - AND("And", WeaviateProtoBase.Filters.Operator.OPERATOR_AND), - OR("Or", WeaviateProtoBase.Filters.Operator.OPERATOR_OR), - NOT("Noe", WeaviateProtoBase.Filters.Operator.OPERATOR_NOT), - - // Comparison operators - EQUAL("Equal", WeaviateProtoBase.Filters.Operator.OPERATOR_EQUAL), - NOT_EQUAL("NotEqual", WeaviateProtoBase.Filters.Operator.OPERATOR_NOT_EQUAL), - LESS_THAN("LessThen", WeaviateProtoBase.Filters.Operator.OPERATOR_LESS_THAN), - LESS_THAN_EQUAL("LessThenEqual", WeaviateProtoBase.Filters.Operator.OPERATOR_LESS_THAN_EQUAL), - GREATER_THAN("GreaterThen", WeaviateProtoBase.Filters.Operator.OPERATOR_GREATER_THAN), - GREATER_THAN_EQUAL("GreaterThenEqual", WeaviateProtoBase.Filters.Operator.OPERATOR_GREATER_THAN_EQUAL), - LIKE("Like", WeaviateProtoBase.Filters.Operator.OPERATOR_LIKE), - CONTAINS_ANY("ContainsAny", WeaviateProtoBase.Filters.Operator.OPERATOR_CONTAINS_ANY), - CONTAINS_ALL("ContainsAll", WeaviateProtoBase.Filters.Operator.OPERATOR_CONTAINS_ALL), - CONTAINS_NONE("ContainsNone", WeaviateProtoBase.Filters.Operator.OPERATOR_CONTAINS_NONE), - WITHIN_GEO_RANGE("WithinGeoRange", WeaviateProtoBase.Filters.Operator.OPERATOR_WITHIN_GEO_RANGE); - - /** String representation for better debug logs. */ - private final String stringValue; - - /** gRPC operator value . */ - private final WeaviateProtoBase.Filters.Operator grpcValue; - - private Operator(String stringValue, WeaviateProtoBase.Filters.Operator grpcValue) { - this.stringValue = stringValue; - this.grpcValue = grpcValue; - } - - public void appendTo(Filters.Builder where) { - where.setOperator(grpcValue); - } - - @Override - public String toString() { - return stringValue; - } - } - - private final Operator operator; - private final List operands; - - @SafeVarargs - private Where(Operator operator, WhereOperand... operands) { - this(operator, Arrays.asList(operands)); - } - - private Where(Operator operator, List operands) { - this.operator = operator; - this.operands = operands; - } - - @Override - public boolean isEmpty() { - // Guard against Where.and(Where.or(), Where.and(), Where.not()) situation. - return operands.isEmpty() - || operands.stream().allMatch(operator -> operator == null | operator.isEmpty()); - } - - @Override - public String toString() { - if (operator == Operator.NOT) { - return "%s %s".formatted(operator, operands.get(0)); - } - var operandStrings = operands.stream().map(Object::toString).toList(); - return "Where(" + String.join(" " + operator.toString() + " ", operandStrings) + ")"; - } - - // Logical operators return a complete operand. - // -------------------------------------------------------------------------- - public static Where and(final WhereOperand... operands) { - return new Where(Operator.AND, operands); - } - - public static Where and(final List operands) { - return new Where(Operator.AND, operands); - } - - public static Where or(final WhereOperand... operands) { - return new Where(Operator.OR, operands); - } - - public static Where or(final List operands) { - return new Where(Operator.OR, operands); - } - - public static Where not(final WhereOperand operand) { - return new Where(Operator.NOT, operand); - } - - /** Negate this expression. */ - public Where not() { - return not(this); - } - - // Comparison operators return fluid builder. - // -------------------------------------------------------------------------- - - /** Filter by object UUID. */ - public static WhereBuilder uuid() { - return property(FetchObjectById.ID_PROPERTY); - } - - /** Filter by object property. */ - public static WhereBuilder property(String property) { - return new WhereBuilder(new PathOperand(property)); - } - - /** Filter by a property of the referenced object. */ - public static WhereBuilder reference(String... path) { - return new WhereBuilder(new PathOperand(path)); - } - - public static class WhereBuilder { - private final WhereOperand left; - - private WhereBuilder(WhereOperand left) { - this.left = left; - } - - // Equal - // ------------------------------------------------------------------------ - public Where eq(String value) { - return new Where(Operator.EQUAL, left, new TextOperand(value)); - } - - public Where eq(String... values) { - return new Where(Operator.EQUAL, left, new TextArrayOperand(values)); - } - - public Where eq(boolean value) { - return new Where(Operator.EQUAL, left, new BooleanOperand(value)); - } - - public Where eq(Boolean... values) { - return new Where(Operator.EQUAL, left, new BooleanArrayOperand(values)); - } - - public Where eq(long value) { - return new Where(Operator.EQUAL, left, new IntegerOperand(value)); - } - - public Where eq(int value) { - return new Where(Operator.EQUAL, left, new IntegerOperand(value)); - } - - public Where eq(Long... values) { - return new Where(Operator.EQUAL, left, new IntegerArrayOperand(values)); - } - - public Where eq(double value) { - return new Where(Operator.EQUAL, left, new NumberOperand(value)); - } - - public Where eq(float value) { - return new Where(Operator.EQUAL, left, new NumberOperand(value)); - } - - public Where eq(Double... values) { - return new Where(Operator.EQUAL, left, new NumberArrayOperand(values)); - } - - public Where eq(OffsetDateTime value) { - return new Where(Operator.EQUAL, left, new DateOperand(value)); - } - - public Where eq(OffsetDateTime... values) { - return new Where(Operator.EQUAL, left, new DateArrayOperand(values)); - } - - public Where eq(Object value) { - return new Where(Operator.EQUAL, left, fromObject(value)); - } - - // NotEqual - // ------------------------------------------------------------------------ - public Where ne(String value) { - return new Where(Operator.NOT_EQUAL, left, new TextOperand(value)); - } - - public Where ne(String... values) { - return new Where(Operator.NOT_EQUAL, left, new TextArrayOperand(values)); - } - - public Where ne(boolean value) { - return new Where(Operator.NOT_EQUAL, left, new BooleanOperand(value)); - } - - public Where ne(Boolean... values) { - return new Where(Operator.NOT_EQUAL, left, new BooleanArrayOperand(values)); - } - - public Where ne(long value) { - return new Where(Operator.NOT_EQUAL, left, new IntegerOperand(value)); - } - - public Where ne(int value) { - return new Where(Operator.NOT_EQUAL, left, new IntegerOperand(value)); - } - - public Where ne(Long... values) { - return new Where(Operator.NOT_EQUAL, left, new IntegerArrayOperand(values)); - } - - public Where ne(double value) { - return new Where(Operator.NOT_EQUAL, left, new NumberOperand(value)); - } - - public Where ne(float value) { - return new Where(Operator.NOT_EQUAL, left, new NumberOperand(value)); - } - - public Where ne(Double... values) { - return new Where(Operator.NOT_EQUAL, left, new NumberArrayOperand(values)); - } - - public Where ne(OffsetDateTime value) { - return new Where(Operator.NOT_EQUAL, left, new DateOperand(value)); - } - - public Where ne(OffsetDateTime... values) { - return new Where(Operator.NOT_EQUAL, left, new DateArrayOperand(values)); - } - - public Where ne(Object value) { - return new Where(Operator.NOT_EQUAL, left, fromObject(value)); - } - - // LessThan - // ------------------------------------------------------------------------ - public Where lt(String value) { - return new Where(Operator.LESS_THAN, left, new TextOperand(value)); - } - - public Where lt(String... values) { - return new Where(Operator.LESS_THAN, left, new TextArrayOperand(values)); - } - - public Where lt(long value) { - return new Where(Operator.LESS_THAN, left, new IntegerOperand(value)); - } - - public Where lt(int value) { - return new Where(Operator.LESS_THAN, left, new IntegerOperand(value)); - } - - public Where lt(Long... values) { - return new Where(Operator.LESS_THAN, left, new IntegerArrayOperand(values)); - } - - public Where lt(double value) { - return new Where(Operator.LESS_THAN, left, new NumberOperand(value)); - } - - public Where lt(float value) { - return new Where(Operator.LESS_THAN, left, new NumberOperand(value)); - } - - public Where lt(Double... values) { - return new Where(Operator.LESS_THAN, left, new NumberArrayOperand(values)); - } - - public Where lt(OffsetDateTime value) { - return new Where(Operator.LESS_THAN, left, new DateOperand(value)); - } - - public Where lt(OffsetDateTime... values) { - return new Where(Operator.LESS_THAN, left, new DateArrayOperand(values)); - } - - public Where lt(Object value) { - return new Where(Operator.LESS_THAN, left, fromObject(value)); - } - - // LessThanEqual - // ------------------------------------------------------------------------ - public Where lte(String value) { - return new Where(Operator.LESS_THAN_EQUAL, left, new TextOperand(value)); - } - - public Where lte(String... values) { - return new Where(Operator.LESS_THAN_EQUAL, left, new TextArrayOperand(values)); - } - - public Where lte(long value) { - return new Where(Operator.LESS_THAN_EQUAL, left, new IntegerOperand(value)); - } - - public Where lte(int value) { - return new Where(Operator.LESS_THAN_EQUAL, left, new IntegerOperand(value)); - } - - public Where lte(Long... values) { - return new Where(Operator.LESS_THAN_EQUAL, left, new IntegerArrayOperand(values)); - } - - public Where lte(double value) { - return new Where(Operator.LESS_THAN_EQUAL, left, new NumberOperand(value)); - } - - public Where lte(float value) { - return new Where(Operator.LESS_THAN_EQUAL, left, new NumberOperand(value)); - } - - public Where lte(Double... values) { - return new Where(Operator.LESS_THAN_EQUAL, left, new NumberArrayOperand(values)); - } - - public Where lte(OffsetDateTime value) { - return new Where(Operator.LESS_THAN_EQUAL, left, new DateOperand(value)); - } - - public Where lte(OffsetDateTime... values) { - return new Where(Operator.LESS_THAN_EQUAL, left, new DateArrayOperand(values)); - } - - public Where lte(Object value) { - return new Where(Operator.LESS_THAN_EQUAL, left, fromObject(value)); - } - - // GreaterThan - // ------------------------------------------------------------------------ - public Where gt(String value) { - return new Where(Operator.GREATER_THAN, left, new TextOperand(value)); - } - - public Where gt(String... values) { - return new Where(Operator.GREATER_THAN, left, new TextArrayOperand(values)); - } - - public Where gt(long value) { - return new Where(Operator.GREATER_THAN, left, new IntegerOperand(value)); - } - - public Where gt(int value) { - return new Where(Operator.GREATER_THAN, left, new IntegerOperand(value)); - } - - public Where gt(Long... values) { - return new Where(Operator.GREATER_THAN, left, new IntegerArrayOperand(values)); - } - - public Where gt(double value) { - return new Where(Operator.GREATER_THAN, left, new NumberOperand(value)); - } - - public Where gt(float value) { - return new Where(Operator.GREATER_THAN, left, new NumberOperand(value)); - } - - public Where gt(Double... values) { - return new Where(Operator.GREATER_THAN, left, new NumberArrayOperand(values)); - } - - public Where gt(OffsetDateTime value) { - return new Where(Operator.GREATER_THAN, left, new DateOperand(value)); - } - - public Where gt(OffsetDateTime... values) { - return new Where(Operator.GREATER_THAN, left, new DateArrayOperand(values)); - } - - public Where gt(Object value) { - return new Where(Operator.GREATER_THAN, left, fromObject(value)); - } - - // GreaterThanEqual - // ------------------------------------------------------------------------ - public Where gte(String value) { - return new Where(Operator.GREATER_THAN_EQUAL, left, new TextOperand(value)); - } - - public Where gte(String... values) { - return new Where(Operator.GREATER_THAN_EQUAL, left, new TextArrayOperand(values)); - } - - public Where gte(long value) { - return new Where(Operator.GREATER_THAN_EQUAL, left, new IntegerOperand(value)); - } - - public Where gte(int value) { - return new Where(Operator.GREATER_THAN_EQUAL, left, new IntegerOperand(value)); - } - - public Where gte(Long... values) { - return new Where(Operator.GREATER_THAN_EQUAL, left, new IntegerArrayOperand(values)); - } - - public Where gte(double value) { - return new Where(Operator.GREATER_THAN_EQUAL, left, new NumberOperand(value)); - } - - public Where gte(float value) { - return new Where(Operator.GREATER_THAN_EQUAL, left, new NumberOperand(value)); - } - - public Where gte(Double... values) { - return new Where(Operator.GREATER_THAN_EQUAL, left, new NumberArrayOperand(values)); - } - - public Where gte(OffsetDateTime value) { - return new Where(Operator.GREATER_THAN_EQUAL, left, new DateOperand(value)); - } - - public Where gte(OffsetDateTime... values) { - return new Where(Operator.GREATER_THAN_EQUAL, left, new DateArrayOperand(values)); - } - - public Where gte(Object value) { - return new Where(Operator.GREATER_THAN_EQUAL, left, fromObject(value)); - } - - // Like - // ------------------------------------------------------------------------ - public Where like(String value) { - return new Where(Operator.LIKE, left, new TextOperand(value)); - } - - // ContainsAny - // ------------------------------------------------------------------------ - public Where containsAny(String value) { - return new Where(Operator.CONTAINS_ANY, left, new TextOperand(value)); - } - - public Where containsAny(String... values) { - return new Where(Operator.CONTAINS_ANY, left, new TextArrayOperand(values)); - } - - public Where containsAny(List values) { - return new Where(Operator.CONTAINS_ANY, left, new TextArrayOperand(values)); - } - - public Where containsAny(Boolean... values) { - return new Where(Operator.CONTAINS_ANY, left, new BooleanArrayOperand(values)); - } - - public Where containsAny(Long... values) { - return new Where(Operator.CONTAINS_ANY, left, new IntegerArrayOperand(values)); - } - - public Where containsAny(Double... values) { - return new Where(Operator.CONTAINS_ANY, left, new NumberArrayOperand(values)); - } - - public Where containsAny(OffsetDateTime... values) { - return new Where(Operator.CONTAINS_ANY, left, new DateArrayOperand(values)); - } - - // ContainsAll - // ------------------------------------------------------------------------ - public Where containsAll(String value) { - return new Where(Operator.CONTAINS_ALL, left, new TextOperand(value)); - } - - public Where containsAll(String... values) { - return new Where(Operator.CONTAINS_ALL, left, new TextArrayOperand(values)); - } - - public Where containsAll(List values) { - return new Where(Operator.CONTAINS_ALL, left, new TextArrayOperand(values)); - } - - public Where containsAll(Boolean... values) { - return new Where(Operator.CONTAINS_ALL, left, new BooleanArrayOperand(values)); - } - - public Where containsAll(Long... values) { - return new Where(Operator.CONTAINS_ALL, left, new IntegerArrayOperand(values)); - } - - public Where containsAll(Double... values) { - return new Where(Operator.CONTAINS_ALL, left, new NumberArrayOperand(values)); - } - - public Where containsAll(OffsetDateTime... values) { - return new Where(Operator.CONTAINS_ALL, left, new DateArrayOperand(values)); - } - - // ContainsNone - // ------------------------------------------------------------------------ - public Where containsNone(String value) { - return new Where(Operator.CONTAINS_NONE, left, new TextOperand(value)); - } - - public Where containsNone(String... values) { - return new Where(Operator.CONTAINS_NONE, left, new TextArrayOperand(values)); - } - - public Where containsNone(List values) { - return new Where(Operator.CONTAINS_NONE, left, new TextArrayOperand(values)); - } - - public Where containsNone(Boolean... values) { - return new Where(Operator.CONTAINS_NONE, left, new BooleanArrayOperand(values)); - } - - public Where containsNone(Long... values) { - return new Where(Operator.CONTAINS_NONE, left, new IntegerArrayOperand(values)); - } - - public Where containsNone(Double... values) { - return new Where(Operator.CONTAINS_NONE, left, new NumberArrayOperand(values)); - } - - public Where containsNone(OffsetDateTime... values) { - return new Where(Operator.CONTAINS_NONE, left, new DateArrayOperand(values)); - } - - // WithinGeoRange - // ------------------------------------------------------------------------ - public Where withinGeoRange(float lat, float lon, float maxDistance) { - return new Where(Operator.WITHIN_GEO_RANGE, left, new GeoRangeOperand(lat, lon, maxDistance)); - } - } - - @Override - public void appendTo(WeaviateProtoBase.Filters.Builder where) { - if (isEmpty()) { - return; - } - - operator.appendTo(where); - - if (operator == Operator.AND || operator == Operator.OR || operator == Operator.NOT) { - operands.forEach(op -> { - var nested = Filters.newBuilder(); - op.appendTo(nested); - where.addFilters(nested); - }); - } else { - // Comparison operators: eq, gt, lt, like, etc. - operands.forEach(op -> op.appendTo(where)); - } - } - - @SuppressWarnings("unchecked") - static WhereOperand fromObject(Object value) { - if (value instanceof String str) { - return new TextOperand(str); - } else if (value instanceof Boolean bool) { - return new BooleanOperand(bool); - } else if (value instanceof Long l) { - return new IntegerOperand(l); - } else if (value instanceof Integer i) { - return new IntegerOperand(i); - } else if (value instanceof Double dbl) { - return new NumberOperand(dbl); - } else if (value instanceof Float f) { - return new NumberOperand(f); - } else if (value instanceof OffsetDateTime date) { - return new DateOperand(date); - } else if (value instanceof String[] strarr) { - return new TextArrayOperand(strarr); - } else if (value instanceof Boolean[] boolarr) { - return new BooleanArrayOperand(boolarr); - } else if (value instanceof Long[] lngarr) { - return new IntegerArrayOperand(lngarr); - } else if (value instanceof Double[] dblarr) { - return new NumberArrayOperand(dblarr); - } else if (value instanceof OffsetDateTime[] datearr) { - return new DateArrayOperand(datearr); - } else if (value instanceof List list) { - if (list.isEmpty()) { - throw new IllegalArgumentException( - "Filter with non-reifiable type (List) cannot be empty, use an array instead"); - } - - Object first = list.get(0); - if (first instanceof String) { - return new TextArrayOperand((List) value); - } else if (first instanceof Boolean) { - return new BooleanArrayOperand((List) value); - } else if (first instanceof Long) { - return new IntegerArrayOperand((List) value); - } else if (first instanceof Double) { - return new NumberArrayOperand((List) value); - } else if (first instanceof OffsetDateTime) { - return new DateArrayOperand((List) value); - } - } - throw new IllegalArgumentException( - "value must be either of String, Boolean, OffsetDateTime, Long, Double, or Array/List of these types"); - } - - private static class PathOperand implements WhereOperand { - private final List path; - - private PathOperand(List path) { - this.path = path; - } - - private PathOperand(String... path) { - this(Arrays.asList(path)); - } - - @Override - public void appendTo(WeaviateProtoBase.Filters.Builder where) { - // "on" is deprecated, but the current proto doesn"t have "path". - if (!path.isEmpty()) { - where.addOn(path.get(0)); - } - // FIXME: no way to reference objects rn? - } - - @Override - public String toString() { - return String.join("::", path); - } - } - - private static class TextOperand implements WhereOperand { - private final String value; - - private TextOperand(String value) { - this.value = value; - } - - @Override - public void appendTo(WeaviateProtoBase.Filters.Builder where) { - where.setValueText(value); - } - - @Override - public String toString() { - return value; - } - } - - private static class TextArrayOperand implements WhereOperand { - private final List values; - - private TextArrayOperand(List values) { - this.values = values; - } - - @SafeVarargs - private TextArrayOperand(String... values) { - this(Arrays.asList(values)); - } - - @Override - public void appendTo(WeaviateProtoBase.Filters.Builder where) { - where.setValueTextArray(WeaviateProtoBase.TextArray.newBuilder().addAllValues(values)); - } - - @Override - public String toString() { - return values.toString(); - } - } - - private static class BooleanOperand implements WhereOperand { - private final boolean value; - - private BooleanOperand(boolean value) { - this.value = value; - } - - @Override - public void appendTo(WeaviateProtoBase.Filters.Builder where) { - where.setValueBoolean(value); - } - - @Override - public String toString() { - return Boolean.toString(value); - } - } - - private static class BooleanArrayOperand implements WhereOperand { - private final List values; - - private BooleanArrayOperand(List values) { - this.values = values; - } - - @SafeVarargs - private BooleanArrayOperand(Boolean... values) { - this(Arrays.asList(values)); - } - - @Override - public void appendTo(WeaviateProtoBase.Filters.Builder where) { - where.setValueBooleanArray(WeaviateProtoBase.BooleanArray.newBuilder().addAllValues(values)); - } - - @Override - public String toString() { - return values.toString(); - } - } - - private static class IntegerOperand implements WhereOperand { - private final long value; - - private IntegerOperand(long value) { - this.value = value; - } - - private IntegerOperand(int value) { - this.value = value; - } - - @Override - public void appendTo(WeaviateProtoBase.Filters.Builder where) { - where.setValueInt(value); - } - - @Override - public String toString() { - return Long.toString(value); - } - } - - private static class IntegerArrayOperand implements WhereOperand { - private final List values; - - private IntegerArrayOperand(List values) { - this.values = values; - } - - @SafeVarargs - private IntegerArrayOperand(Long... values) { - this(Arrays.asList(values)); - } - - @Override - public void appendTo(WeaviateProtoBase.Filters.Builder where) { - where.setValueIntArray(WeaviateProtoBase.IntArray.newBuilder().addAllValues(values)); - } - - @Override - public String toString() { - return values.toString(); - } - } - - private static class NumberOperand implements WhereOperand { - private final double value; - - private NumberOperand(double value) { - this.value = value; - } - - private NumberOperand(float value) { - this.value = value; - } - - @Override - public void appendTo(WeaviateProtoBase.Filters.Builder where) { - where.setValueNumber(value); - } - - @Override - public String toString() { - return Double.toString(value); - } - } - - private static class NumberArrayOperand implements WhereOperand { - private final List values; - - private NumberArrayOperand(List values) { - this.values = values; - } - - @SafeVarargs - private NumberArrayOperand(Double... values) { - this(Arrays.asList(values)); - } - - @Override - public void appendTo(WeaviateProtoBase.Filters.Builder where) { - where.setValueNumberArray(WeaviateProtoBase.NumberArray.newBuilder().addAllValues(values)); - } - - @Override - public String toString() { - return values.toString(); - } - } - - private static class DateOperand implements WhereOperand { - private final OffsetDateTime value; - - private DateOperand(OffsetDateTime value) { - this.value = value; - } - - @Override - public void appendTo(WeaviateProtoBase.Filters.Builder where) { - where.setValueText(value.toString()); - } - - @Override - public String toString() { - return value.toString(); - } - } - - private static class DateArrayOperand implements WhereOperand { - private final List values; - - private DateArrayOperand(List values) { - this.values = values; - } - - @SafeVarargs - private DateArrayOperand(OffsetDateTime... values) { - this(Arrays.asList(values)); - } - - private List formatted() { - return values.stream().map(OffsetDateTime::toString).toList(); - } - - @Override - public void appendTo(WeaviateProtoBase.Filters.Builder where) { - where.setValueTextArray(WeaviateProtoBase.TextArray.newBuilder().addAllValues(formatted())); - } - - @Override - public String toString() { - return values.toString(); - } - } - - private static class GeoRangeOperand implements WhereOperand { - private final float lat; - private final float lon; - private final float distance; - - private GeoRangeOperand(float lat, float lon, float distance) { - this.lat = lat; - this.lon = lon; - this.distance = distance; - } - - @Override - public void appendTo(WeaviateProtoBase.Filters.Builder where) { - where.setValueGeo(WeaviateProtoBase.GeoCoordinatesFilter.newBuilder() - .setLatitude(lat).setLongitude(lon).setDistance(distance)); - } - - @Override - public String toString() { - return "(lat=%d, lon=%d, distance=%d)".formatted(lat, lon, distance); - } - } -}