From 9ba00107fec3ce4f2a67542c2932de0933720278 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 25 Aug 2025 11:39:15 +0200 Subject: [PATCH 01/17] feat: add BOOLEAN data type --- .../client6/v1/api/collections/DataType.java | 3 +- .../client6/v1/api/collections/Property.java | 18 ++++- .../aggregate/AggregateRequest.java | 9 ++- .../aggregate/AggregateResponse.java | 9 +++ .../aggregate/AggregateResponseGroup.java | 9 +++ .../collections/aggregate/Aggregation.java | 25 ++++--- .../aggregate/BooleanAggregation.java | 68 +++++++++++++++++++ .../api/collections/aggregate/GroupedBy.java | 9 +++ .../aggregate/IntegerAggregation.java | 6 +- 9 files changed, 137 insertions(+), 19 deletions(-) create mode 100644 src/main/java/io/weaviate/client6/v1/api/collections/aggregate/BooleanAggregation.java diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java index c114f0ab5..567cd60df 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java @@ -8,6 +8,7 @@ public interface DataType { public static final String TEXT = "text"; public static final String INT = "int"; public static final String BLOB = "blob"; + public static final String BOOL = "boolean"; - public static final Set KNOWN_TYPES = ImmutableSet.of(TEXT, INT, BLOB); + public static final Set KNOWN_TYPES = ImmutableSet.of(TEXT, INT, BLOB, BOOL); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/Property.java b/src/main/java/io/weaviate/client6/v1/api/collections/Property.java index 08e638032..be1eaf1f9 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/Property.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/Property.java @@ -24,7 +24,7 @@ public static Property text(String name) { } public static Property text(String name, Function> fn) { - return fn.apply(new Builder(name, DataType.TEXT)).build(); + return newProperty(name, DataType.TEXT, fn); } public static Property integer(String name) { @@ -32,7 +32,7 @@ public static Property integer(String name) { } public static Property integer(String name, Function> fn) { - return fn.apply(new Builder(name, DataType.INT)).build(); + return newProperty(name, DataType.INT, fn); } public static Property blob(String name) { @@ -40,7 +40,19 @@ public static Property blob(String name) { } public static Property blob(String name, Function> fn) { - return fn.apply(new Builder(name, DataType.BLOB)).build(); + return newProperty(name, DataType.BLOB, fn); + } + + public static Property bool(String name) { + return bool(name, ObjectBuilder.identity()); + } + + public static Property bool(String name, Function> fn) { + return newProperty(name, DataType.BOOL, fn); + } + + private static Property newProperty(String name, String dataType, Function> fn) { + return fn.apply(new Builder(name, dataType)).build(); } public static ReferenceProperty reference(String name, String... collections) { 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..28129f3cf 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 @@ -101,7 +101,14 @@ private static Map unmarshalAggregation(WeaviateProtoAggregate.A value = new TextAggregation.Values( metric.hasCount() ? metric.getCount() : null, topOccurrences); - + } else if (aggregation.hasBoolean()) { + var metric = aggregation.getBoolean(); + value = new BooleanAggregation.Values( + metric.hasCount() ? metric.getCount() : null, + metric.hasPercentageFalse() ? Float.valueOf((float) metric.getPercentageFalse()) : null, + metric.hasPercentageTrue() ? Float.valueOf((float) metric.getPercentageTrue()) : null, + metric.hasTotalFalse() ? metric.getTotalFalse() : null, + metric.hasTotalTrue() ? metric.getTotalTrue() : null); } else { assert false : "branch not covered"; } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponse.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponse.java index 87b94db81..18c3d1c0d 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponse.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponse.java @@ -22,6 +22,15 @@ public IntegerAggregation.Values integer(String name) { return (IntegerAggregation.Values) this.properties.get(name); } + public boolean isBool(String name) { + return properties.get(name) instanceof BooleanAggregation.Values; + } + + public BooleanAggregation.Values bool(String name) { + checkPropertyType(name, this::isBool, "Boolean"); + return (BooleanAggregation.Values) this.properties.get(name); + } + private void checkPropertyType(String name, Function check, String expected) { if (!check.apply(name)) { throw new IllegalStateException(name + "is not a " + expected + " property"); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponseGroup.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponseGroup.java index 7f28a84c3..024026fc8 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponseGroup.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponseGroup.java @@ -23,6 +23,15 @@ public IntegerAggregation.Values integer(String name) { return (IntegerAggregation.Values) this.properties.get(name); } + public boolean isBool(String name) { + return properties.get(name) instanceof BooleanAggregation.Values; + } + + public BooleanAggregation.Values bool(String name) { + checkPropertyType(name, this::isBool, "Boolean"); + return (BooleanAggregation.Values) this.properties.get(name); + } + private void checkPropertyType(String name, Function check, String expected) { if (!check.apply(name)) { throw new IllegalStateException(name + "is not a " + expected + " property"); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/Aggregation.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/Aggregation.java index 5246e7074..e93b01da8 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/Aggregation.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/Aggregation.java @@ -22,6 +22,21 @@ public static Aggregation of(AggregateObjectFilter objectFilter, Function> fn) { + return TextAggregation.of(property, fn); + } + + public static final PropertyAggregation integer(String property, + Function> fn) { + return IntegerAggregation.of(property, fn); + } + + public static final PropertyAggregation bool(String property, + Function> fn) { + return BooleanAggregation.of(property, fn); + } + public Aggregation(Builder builder) { this( builder.objectFilter, @@ -63,16 +78,6 @@ public Aggregation build() { } } - public static final PropertyAggregation text(String property, - Function> fn) { - return TextAggregation.of(property, fn); - } - - public static final PropertyAggregation integer(String property, - Function> fn) { - return IntegerAggregation.of(property, fn); - } - public void appendTo(WeaviateProtoAggregate.AggregateRequest.Builder req) { if (filter != null) { filter.appendTo(req); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/BooleanAggregation.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/BooleanAggregation.java new file mode 100644 index 000000000..223aad546 --- /dev/null +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/BooleanAggregation.java @@ -0,0 +1,68 @@ +package io.weaviate.client6.v1.api.collections.aggregate; + +import java.util.Set; +import java.util.function.Function; + +import io.weaviate.client6.v1.internal.ObjectBuilder; +import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoAggregate; + +public class BooleanAggregation + extends AbstractPropertyAggregation { + + public BooleanAggregation(String property, + Set> metrics) { + super(property, metrics); + } + + public static BooleanAggregation of(String property, Function> fn) { + return fn.apply(new Builder(property)).build(); + } + + public BooleanAggregation(Builder builder) { + this(builder.property, builder.metrics); + } + + public static class Builder extends + AbstractPropertyAggregation.Builder { + + public Builder(String property) { + super(property); + } + + public final Builder count() { + return addMetric(WeaviateProtoAggregate.AggregateRequest.Aggregation.Boolean.Builder::setCount); + } + + public final Builder percentageFalse() { + return addMetric(WeaviateProtoAggregate.AggregateRequest.Aggregation.Boolean.Builder::setPercentageFalse); + } + + public final Builder percentageTrue() { + return addMetric(WeaviateProtoAggregate.AggregateRequest.Aggregation.Boolean.Builder::setPercentageTrue); + } + + public final Builder totalFalse() { + return addMetric(WeaviateProtoAggregate.AggregateRequest.Aggregation.Boolean.Builder::setTotalFalse); + } + + public final Builder totalTrue() { + return addMetric(WeaviateProtoAggregate.AggregateRequest.Aggregation.Boolean.Builder::setTotalTrue); + } + + @Override + public final BooleanAggregation build() { + return new BooleanAggregation(this); + } + } + + public record Values(Long count, Float percentageFalse, Float percentageTrue, Long totalFalse, Long totalTrue) { + } + + @Override + public void appendTo(WeaviateProtoAggregate.AggregateRequest.Aggregation.Builder req) { + super.appendTo(req); + var bool = WeaviateProtoAggregate.AggregateRequest.Aggregation.Boolean.newBuilder(); + appendMetrics(bool); + req.setBoolean(bool); + } +} diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java index f853780c7..4cfa2e49a 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java @@ -21,6 +21,15 @@ public Long integer() { return (Long) value; } + public boolean isBool() { + return value instanceof Long; + } + + public Boolean bool() { + checkPropertyType(this::isBool, "Boolean"); + return (Boolean) value; + } + private void checkPropertyType(Supplier check, String expected) { if (!check.get()) { throw new IllegalStateException(property + "is not a " + expected + " property"); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/IntegerAggregation.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/IntegerAggregation.java index 5f8f1db00..9d674e4b3 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/IntegerAggregation.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/IntegerAggregation.java @@ -10,8 +10,7 @@ public class IntegerAggregation extends AbstractPropertyAggregation { public IntegerAggregation(String property, - Set> metrics, - Integer topOccurrencesCutoff) { + Set> metrics) { super(property, metrics); } @@ -20,12 +19,11 @@ public static IntegerAggregation of(String property, Function { - private Integer topOccurrencesCutoff; public Builder(String property) { super(property); From dcc5644843f1c53853cbe0af2ce659cfc7f180ed Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 25 Aug 2025 13:15:58 +0200 Subject: [PATCH 02/17] feat: add DATE data type Switch from representing Weaviate dates as (legacy) Date to modern and more accurate OffsetDateTime, such that the information is not lost --- .../client6/v1/api/collections/DataType.java | 3 +- .../client6/v1/api/collections/Property.java | 8 +++ .../aggregate/AggregateRequest.java | 11 +++ .../aggregate/AggregateResponse.java | 9 +++ .../aggregate/AggregateResponseGroup.java | 9 +++ .../aggregate/DateAggregation.java | 69 +++++++++++++++++++ .../api/collections/aggregate/GroupedBy.java | 2 +- .../api/collections/query/QueryRequest.java | 11 ++- .../client6/v1/internal/DateUtil.java | 11 +++ .../client6/v1/internal/orm/MapBuilder.java | 4 +- .../v1/internal/orm/PropertiesBuilder.java | 4 +- 11 files changed, 129 insertions(+), 12 deletions(-) create mode 100644 src/main/java/io/weaviate/client6/v1/api/collections/aggregate/DateAggregation.java create mode 100644 src/main/java/io/weaviate/client6/v1/internal/DateUtil.java diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java index 567cd60df..3eef2094f 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java @@ -9,6 +9,7 @@ public interface DataType { public static final String INT = "int"; public static final String BLOB = "blob"; public static final String BOOL = "boolean"; + public static final String DATE = "date"; - public static final Set KNOWN_TYPES = ImmutableSet.of(TEXT, INT, BLOB, BOOL); + public static final Set KNOWN_TYPES = ImmutableSet.of(TEXT, INT, BLOB, BOOL, DATE); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/Property.java b/src/main/java/io/weaviate/client6/v1/api/collections/Property.java index be1eaf1f9..343bccf2a 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/Property.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/Property.java @@ -51,6 +51,14 @@ public static Property bool(String name, Function> fn) { + return newProperty(name, DataType.DATE, fn); + } + private static Property newProperty(String name, String dataType, Function> fn) { return fn.apply(new Builder(name, dataType)).build(); } 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 28129f3cf..0230b3bd3 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.internal.DateUtil; 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; @@ -59,6 +60,8 @@ static Rpc(property, groupBy.getInt()); } else if (groupBy.hasText()) { groupedBy = new GroupedBy(property, groupBy.getText()); + } else if (groupBy.hasBoolean()) { + groupedBy = new GroupedBy(property, groupBy.getBoolean()); } else { assert false : "(aggregate) branch not covered"; } @@ -109,6 +112,14 @@ private static Map unmarshalAggregation(WeaviateProtoAggregate.A metric.hasPercentageTrue() ? Float.valueOf((float) metric.getPercentageTrue()) : null, metric.hasTotalFalse() ? metric.getTotalFalse() : null, metric.hasTotalTrue() ? metric.getTotalTrue() : null); + } else if (aggregation.hasDate()) { + var metric = aggregation.getDate(); + value = new DateAggregation.Values( + metric.hasCount() ? metric.getCount() : null, + metric.hasMinimum() ? DateUtil.fromISO8601(metric.getMinimum()) : null, + metric.hasMaximum() ? DateUtil.fromISO8601(metric.getMaximum()) : null, + metric.hasMedian() ? DateUtil.fromISO8601(metric.getMedian()) : null, + metric.hasMode() ? DateUtil.fromISO8601(metric.getMode()) : null); } else { assert false : "branch not covered"; } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponse.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponse.java index 18c3d1c0d..898d33243 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponse.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponse.java @@ -31,6 +31,15 @@ public BooleanAggregation.Values bool(String name) { return (BooleanAggregation.Values) this.properties.get(name); } + public boolean isDate(String name) { + return properties.get(name) instanceof DateAggregation.Values; + } + + public DateAggregation.Values date(String name) { + checkPropertyType(name, this::isDate, "Date"); + return (DateAggregation.Values) this.properties.get(name); + } + private void checkPropertyType(String name, Function check, String expected) { if (!check.apply(name)) { throw new IllegalStateException(name + "is not a " + expected + " property"); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponseGroup.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponseGroup.java index 024026fc8..5e4d69bb4 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponseGroup.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponseGroup.java @@ -32,6 +32,15 @@ public BooleanAggregation.Values bool(String name) { return (BooleanAggregation.Values) this.properties.get(name); } + public boolean isDate(String name) { + return properties.get(name) instanceof DateAggregation.Values; + } + + public DateAggregation.Values date(String name) { + checkPropertyType(name, this::isDate, "Date"); + return (DateAggregation.Values) this.properties.get(name); + } + private void checkPropertyType(String name, Function check, String expected) { if (!check.apply(name)) { throw new IllegalStateException(name + "is not a " + expected + " property"); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/DateAggregation.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/DateAggregation.java new file mode 100644 index 000000000..3dc8c4ac0 --- /dev/null +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/DateAggregation.java @@ -0,0 +1,69 @@ +package io.weaviate.client6.v1.api.collections.aggregate; + +import java.time.OffsetDateTime; +import java.util.Set; +import java.util.function.Function; + +import io.weaviate.client6.v1.internal.ObjectBuilder; +import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoAggregate; + +public class DateAggregation + extends AbstractPropertyAggregation { + + public DateAggregation(String property, + Set> metrics) { + super(property, metrics); + } + + public static DateAggregation of(String property, Function> fn) { + return fn.apply(new Builder(property)).build(); + } + + public DateAggregation(Builder builder) { + this(builder.property, builder.metrics); + } + + public static class Builder extends + AbstractPropertyAggregation.Builder { + + public Builder(String property) { + super(property); + } + + public final Builder count() { + return addMetric(WeaviateProtoAggregate.AggregateRequest.Aggregation.Date.Builder::setCount); + } + + public Builder min() { + return addMetric(WeaviateProtoAggregate.AggregateRequest.Aggregation.Date.Builder::setMinimum); + } + + public Builder max() { + return addMetric(WeaviateProtoAggregate.AggregateRequest.Aggregation.Date.Builder::setMaximum); + } + + public Builder median() { + return addMetric(WeaviateProtoAggregate.AggregateRequest.Aggregation.Date.Builder::setMedian); + } + + public Builder mode() { + return addMetric(WeaviateProtoAggregate.AggregateRequest.Aggregation.Date.Builder::setMode); + } + + @Override + public final DateAggregation build() { + return new DateAggregation(this); + } + } + + public record Values(Long count, OffsetDateTime min, OffsetDateTime max, OffsetDateTime median, OffsetDateTime mode) { + } + + @Override + public void appendTo(WeaviateProtoAggregate.AggregateRequest.Aggregation.Builder req) { + super.appendTo(req); + var date = WeaviateProtoAggregate.AggregateRequest.Aggregation.Date.newBuilder(); + appendMetrics(date); + req.setDate(date); + } +} diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java index 4cfa2e49a..cc64aa81e 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java @@ -22,7 +22,7 @@ public Long integer() { } public boolean isBool() { - return value instanceof Long; + return value instanceof Boolean; } public Boolean bool() { 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..e772fe65d 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 @@ -1,8 +1,6 @@ package io.weaviate.client6.v1.api.collections.query; -import java.time.OffsetDateTime; import java.util.ArrayList; -import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.function.Function; @@ -12,6 +10,7 @@ import io.weaviate.client6.v1.api.collections.ObjectMetadata; import io.weaviate.client6.v1.api.collections.Vectors; import io.weaviate.client6.v1.api.collections.WeaviateObject; +import io.weaviate.client6.v1.internal.DateUtil; import io.weaviate.client6.v1.internal.grpc.ByteStringUtil; import io.weaviate.client6.v1.internal.grpc.Rpc; import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateGrpc.WeaviateBlockingStub; @@ -168,12 +167,13 @@ private static WeaviateObject unmarshalWithRefere var vectors = new Vectors.Builder(); for (final var vector : metadataResult.getVectorsList()) { var vectorName = vector.getName(); + var vbytes = vector.getVectorBytes(); switch (vector.getType()) { case VECTOR_TYPE_SINGLE_FP32: - vectors.vector(vectorName, ByteStringUtil.decodeVectorSingle(vector.getVectorBytes())); + vectors.vector(vectorName, ByteStringUtil.decodeVectorSingle(vbytes)); break; case VECTOR_TYPE_MULTI_FP32: - vectors.vector(vectorName, ByteStringUtil.decodeVectorMulti(vector.getVectorBytes())); + vectors.vector(vectorName, ByteStringUtil.decodeVectorMulti(vbytes)); break; default: continue; @@ -206,8 +206,7 @@ private static void setProperty(String property, WeaviateProtoProperties.Val } else if (value.hasBlobValue()) { builder.setBlob(property, value.getBlobValue()); } else if (value.hasDateValue()) { - OffsetDateTime offsetDateTime = OffsetDateTime.parse(value.getDateValue()); - builder.setDate(property, Date.from(offsetDateTime.toInstant())); + builder.setOffsetDateTime(property, DateUtil.fromISO8601(value.getDateValue())); } else { assert false : "(query) branch not covered"; } diff --git a/src/main/java/io/weaviate/client6/v1/internal/DateUtil.java b/src/main/java/io/weaviate/client6/v1/internal/DateUtil.java new file mode 100644 index 000000000..c7433cd75 --- /dev/null +++ b/src/main/java/io/weaviate/client6/v1/internal/DateUtil.java @@ -0,0 +1,11 @@ +package io.weaviate.client6.v1.internal; + +import java.time.OffsetDateTime; + +public final class DateUtil { + + /** Convert ISO8601-formatted time string to {@Olink OffsetDateTime}. */ + public static OffsetDateTime fromISO8601(String iso8601) { + return OffsetDateTime.parse(iso8601); + } +} diff --git a/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java b/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java index c45bd57a4..2b63c8a84 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java +++ b/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java @@ -1,6 +1,6 @@ package io.weaviate.client6.v1.internal.orm; -import java.util.Date; +import java.time.OffsetDateTime; import java.util.HashMap; import java.util.Map; @@ -38,7 +38,7 @@ public void setBlob(String property, String value) { } @Override - public void setDate(String property, Date value) { + public void setOffsetDateTime(String property, OffsetDateTime value) { properties.put(property, value); } diff --git a/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java b/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java index 0d88d385c..a61676c0a 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java +++ b/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java @@ -1,6 +1,6 @@ package io.weaviate.client6.v1.internal.orm; -import java.util.Date; +import java.time.OffsetDateTime; public interface PropertiesBuilder { void setNull(String property); @@ -15,7 +15,7 @@ public interface PropertiesBuilder { void setBlob(String property, String value); - void setDate(String property, Date value); + void setOffsetDateTime(String property, OffsetDateTime value); T build(); } From 8fb14c63f949857e4b8dff54b19ff5404131f655 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 25 Aug 2025 13:24:13 +0200 Subject: [PATCH 03/17] feat: add UUID data type --- .../io/weaviate/client6/v1/api/collections/DataType.java | 3 ++- .../io/weaviate/client6/v1/api/collections/Property.java | 8 ++++++++ .../client6/v1/api/collections/query/QueryRequest.java | 3 +++ .../io/weaviate/client6/v1/internal/orm/MapBuilder.java | 6 ++++++ .../client6/v1/internal/orm/PropertiesBuilder.java | 2 ++ 5 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java index 3eef2094f..e2dab2ff2 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java @@ -10,6 +10,7 @@ public interface DataType { public static final String BLOB = "blob"; public static final String BOOL = "boolean"; public static final String DATE = "date"; + public static final String UUID = "uuid"; - public static final Set KNOWN_TYPES = ImmutableSet.of(TEXT, INT, BLOB, BOOL, DATE); + public static final Set KNOWN_TYPES = ImmutableSet.of(TEXT, INT, BLOB, BOOL, DATE, UUID); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/Property.java b/src/main/java/io/weaviate/client6/v1/api/collections/Property.java index 343bccf2a..ebe2b46ea 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/Property.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/Property.java @@ -59,6 +59,14 @@ public static Property date(String name, Function> fn) { + return newProperty(name, DataType.UUID, fn); + } + private static Property newProperty(String name, String dataType, Function> fn) { return fn.apply(new Builder(name, dataType)).build(); } 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 e772fe65d..62a08f039 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 @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.UUID; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -207,6 +208,8 @@ private static void setProperty(String property, WeaviateProtoProperties.Val builder.setBlob(property, value.getBlobValue()); } else if (value.hasDateValue()) { builder.setOffsetDateTime(property, DateUtil.fromISO8601(value.getDateValue())); + } else if (value.hasUuidValue()) { + builder.setUuid(property, UUID.fromString(value.getUuidValue())); } else { assert false : "(query) branch not covered"; } diff --git a/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java b/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java index 2b63c8a84..ae4b9ba9e 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java +++ b/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java @@ -3,6 +3,7 @@ import java.time.OffsetDateTime; import java.util.HashMap; import java.util.Map; +import java.util.UUID; public class MapBuilder implements PropertiesBuilder> { private final Map properties = new HashMap<>(); @@ -42,6 +43,11 @@ public void setOffsetDateTime(String property, OffsetDateTime value) { properties.put(property, value); } + @Override + public void setUuid(String property, UUID value) { + properties.put(property, value); + } + @Override public Map build() { return properties; diff --git a/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java b/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java index a61676c0a..fb5e53b54 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java +++ b/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java @@ -17,5 +17,7 @@ public interface PropertiesBuilder { void setOffsetDateTime(String property, OffsetDateTime value); + void setUuid(String property, UUID uuid); + T build(); } From c016973c5ea93d708c69a2c29645eb89b1ca651b Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 25 Aug 2025 13:36:26 +0200 Subject: [PATCH 04/17] feat: add Number data type --- .../client6/v1/api/collections/DataType.java | 3 +- .../client6/v1/api/collections/Property.java | 8 ++ .../aggregate/AggregateRequest.java | 13 ++++ .../aggregate/AggregateResponse.java | 9 +++ .../aggregate/AggregateResponseGroup.java | 9 +++ .../collections/aggregate/Aggregation.java | 10 +++ .../api/collections/aggregate/GroupedBy.java | 9 +++ .../aggregate/NumberAggregation.java | 76 +++++++++++++++++++ .../api/collections/query/QueryRequest.java | 2 +- .../client6/v1/internal/orm/MapBuilder.java | 2 +- .../v1/internal/orm/PropertiesBuilder.java | 3 +- 11 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 src/main/java/io/weaviate/client6/v1/api/collections/aggregate/NumberAggregation.java diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java index e2dab2ff2..0e9027d41 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java @@ -11,6 +11,7 @@ public interface DataType { public static final String BOOL = "boolean"; public static final String DATE = "date"; public static final String UUID = "uuid"; + public static final String NUMBER = "number"; - public static final Set KNOWN_TYPES = ImmutableSet.of(TEXT, INT, BLOB, BOOL, DATE, UUID); + public static final Set KNOWN_TYPES = ImmutableSet.of(TEXT, INT, BLOB, BOOL, DATE, UUID, NUMBER); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/Property.java b/src/main/java/io/weaviate/client6/v1/api/collections/Property.java index ebe2b46ea..b1458c4bd 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/Property.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/Property.java @@ -67,6 +67,14 @@ public static Property uuid(String name, Function> fn) { + return newProperty(name, DataType.NUMBER, fn); + } + private static Property newProperty(String name, String dataType, Function> fn) { return fn.apply(new Builder(name, dataType)).build(); } 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 0230b3bd3..7fb57895d 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 @@ -62,6 +62,8 @@ static Rpc(property, groupBy.getText()); } else if (groupBy.hasBoolean()) { groupedBy = new GroupedBy(property, groupBy.getBoolean()); + } else if (groupBy.hasNumber()) { + groupedBy = new GroupedBy(property, groupBy.getNumber()); } else { assert false : "(aggregate) branch not covered"; } @@ -74,6 +76,7 @@ static Rpc rpc.method(), () -> rpc.methodAsync()); + } private static Map unmarshalAggregation(WeaviateProtoAggregate.AggregateReply.Aggregations result) { @@ -120,6 +123,16 @@ private static Map unmarshalAggregation(WeaviateProtoAggregate.A metric.hasMaximum() ? DateUtil.fromISO8601(metric.getMaximum()) : null, metric.hasMedian() ? DateUtil.fromISO8601(metric.getMedian()) : null, metric.hasMode() ? DateUtil.fromISO8601(metric.getMode()) : null); + } else if (aggregation.hasNumber()) { + var metric = aggregation.getNumber(); + value = new NumberAggregation.Values( + metric.hasCount() ? metric.getCount() : null, + metric.hasMinimum() ? metric.getMinimum() : null, + metric.hasMaximum() ? metric.getMaximum() : null, + metric.hasMean() ? metric.getMean() : null, + metric.hasMedian() ? metric.getMedian() : null, + metric.hasMode() ? metric.getMode() : null, + metric.hasSum() ? metric.getSum() : null); } else { assert false : "branch not covered"; } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponse.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponse.java index 898d33243..2a2ecf60a 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponse.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponse.java @@ -40,6 +40,15 @@ public DateAggregation.Values date(String name) { return (DateAggregation.Values) this.properties.get(name); } + public boolean isNumber(String name) { + return properties.get(name) instanceof NumberAggregation.Values; + } + + public NumberAggregation.Values number(String name) { + checkPropertyType(name, this::isNumber, "Number"); + return (NumberAggregation.Values) this.properties.get(name); + } + private void checkPropertyType(String name, Function check, String expected) { if (!check.apply(name)) { throw new IllegalStateException(name + "is not a " + expected + " property"); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponseGroup.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponseGroup.java index 5e4d69bb4..08cb33146 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponseGroup.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponseGroup.java @@ -41,6 +41,15 @@ public DateAggregation.Values date(String name) { return (DateAggregation.Values) this.properties.get(name); } + public boolean isNumber(String name) { + return properties.get(name) instanceof NumberAggregation.Values; + } + + public NumberAggregation.Values number(String name) { + checkPropertyType(name, this::isNumber, "Number"); + return (NumberAggregation.Values) this.properties.get(name); + } + private void checkPropertyType(String name, Function check, String expected) { if (!check.apply(name)) { throw new IllegalStateException(name + "is not a " + expected + " property"); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/Aggregation.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/Aggregation.java index e93b01da8..4dd8cb75f 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/Aggregation.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/Aggregation.java @@ -37,6 +37,16 @@ public static final PropertyAggregation bool(String property, return BooleanAggregation.of(property, fn); } + public static final PropertyAggregation date(String property, + Function> fn) { + return DateAggregation.of(property, fn); + } + + public static final PropertyAggregation number(String property, + Function> fn) { + return NumberAggregation.of(property, fn); + } + public Aggregation(Builder builder) { this( builder.objectFilter, diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java index cc64aa81e..6a67d37db 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java @@ -30,6 +30,15 @@ public Boolean bool() { return (Boolean) value; } + public boolean isNumber() { + return value instanceof Double; + } + + public Double number() { + checkPropertyType(this::isNumber, "Number"); + return (Double) value; + } + private void checkPropertyType(Supplier check, String expected) { if (!check.get()) { throw new IllegalStateException(property + "is not a " + expected + " property"); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/NumberAggregation.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/NumberAggregation.java new file mode 100644 index 000000000..55a4779ec --- /dev/null +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/NumberAggregation.java @@ -0,0 +1,76 @@ +package io.weaviate.client6.v1.api.collections.aggregate; + +import java.util.Set; +import java.util.function.Function; + +import io.weaviate.client6.v1.internal.ObjectBuilder; +import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoAggregate; + +public class NumberAggregation + extends AbstractPropertyAggregation { + + public NumberAggregation(String property, + Set> metrics) { + super(property, metrics); + } + + public static NumberAggregation of(String property, Function> fn) { + return fn.apply(new Builder(property)).build(); + } + + public NumberAggregation(Builder builder) { + this(builder.property, builder.metrics); + } + + public static class Builder extends + AbstractPropertyAggregation.Builder { + + public Builder(String property) { + super(property); + } + + public final Builder count() { + return addMetric(WeaviateProtoAggregate.AggregateRequest.Aggregation.Number.Builder::setCount); + } + + public Builder min() { + return addMetric(WeaviateProtoAggregate.AggregateRequest.Aggregation.Number.Builder::setMinimum); + } + + public Builder max() { + return addMetric(WeaviateProtoAggregate.AggregateRequest.Aggregation.Number.Builder::setMaximum); + } + + public Builder mean() { + return addMetric(WeaviateProtoAggregate.AggregateRequest.Aggregation.Number.Builder::setMean); + } + + public Builder median() { + return addMetric(WeaviateProtoAggregate.AggregateRequest.Aggregation.Number.Builder::setMedian); + } + + public Builder mode() { + return addMetric(WeaviateProtoAggregate.AggregateRequest.Aggregation.Number.Builder::setMode); + } + + public Builder sum() { + return addMetric(WeaviateProtoAggregate.AggregateRequest.Aggregation.Number.Builder::setSum); + } + + @Override + public final NumberAggregation build() { + return new NumberAggregation(this); + } + } + + public record Values(Long count, Double min, Double max, Double mean, Double median, Double mode, Double sum) { + } + + @Override + public void appendTo(WeaviateProtoAggregate.AggregateRequest.Aggregation.Builder req) { + super.appendTo(req); + var number = WeaviateProtoAggregate.AggregateRequest.Aggregation.Number.newBuilder(); + appendMetrics(number); + req.setNumber(number); + } +} 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 62a08f039..264356402 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 @@ -203,7 +203,7 @@ private static void setProperty(String property, WeaviateProtoProperties.Val } else if (value.hasIntValue()) { builder.setInteger(property, value.getIntValue()); } else if (value.hasNumberValue()) { - builder.setNumber(property, value.getNumberValue()); + builder.setDouble(property, value.getNumberValue()); } else if (value.hasBlobValue()) { builder.setBlob(property, value.getBlobValue()); } else if (value.hasDateValue()) { diff --git a/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java b/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java index ae4b9ba9e..83581e193 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java +++ b/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java @@ -29,7 +29,7 @@ public void setInteger(String property, Long value) { } @Override - public void setNumber(String property, Number value) { + public void setDouble(String property, Double value) { properties.put(property, value); } diff --git a/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java b/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java index fb5e53b54..561bd677e 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java +++ b/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java @@ -1,6 +1,7 @@ package io.weaviate.client6.v1.internal.orm; import java.time.OffsetDateTime; +import java.util.UUID; public interface PropertiesBuilder { void setNull(String property); @@ -11,7 +12,7 @@ public interface PropertiesBuilder { void setInteger(String property, Long value); - void setNumber(String property, Number value); + void setDouble(String property, Double value); void setBlob(String property, String value); From 533d1802bde97a68ad84779a0f5a60afbbde4934 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 25 Aug 2025 13:40:44 +0200 Subject: [PATCH 05/17] chore: capitalize Weaviate data types in the exception message This should disambiguate errors which otherwise appear to refer to Java builin data types. E.g. all numbers extend Number, and yet an exception might say that 'amoung_long' is not a NUMBER property --- .../api/collections/aggregate/AggregateResponse.java | 10 +++++----- .../collections/aggregate/AggregateResponseGroup.java | 10 +++++----- .../v1/api/collections/aggregate/GroupedBy.java | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponse.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponse.java index 2a2ecf60a..fb4671338 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponse.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponse.java @@ -9,7 +9,7 @@ public boolean isText(String name) { } public TextAggregation.Values text(String name) { - checkPropertyType(name, this::isText, "Text"); + checkPropertyType(name, this::isText, "TEXT"); return (TextAggregation.Values) this.properties.get(name); } @@ -18,7 +18,7 @@ public boolean isInteger(String name) { } public IntegerAggregation.Values integer(String name) { - checkPropertyType(name, this::isInteger, "Integer"); + checkPropertyType(name, this::isInteger, "INTEGER"); return (IntegerAggregation.Values) this.properties.get(name); } @@ -27,7 +27,7 @@ public boolean isBool(String name) { } public BooleanAggregation.Values bool(String name) { - checkPropertyType(name, this::isBool, "Boolean"); + checkPropertyType(name, this::isBool, "BOOLEAN"); return (BooleanAggregation.Values) this.properties.get(name); } @@ -36,7 +36,7 @@ public boolean isDate(String name) { } public DateAggregation.Values date(String name) { - checkPropertyType(name, this::isDate, "Date"); + checkPropertyType(name, this::isDate, "DATE"); return (DateAggregation.Values) this.properties.get(name); } @@ -45,7 +45,7 @@ public boolean isNumber(String name) { } public NumberAggregation.Values number(String name) { - checkPropertyType(name, this::isNumber, "Number"); + checkPropertyType(name, this::isNumber, "NUMBER"); return (NumberAggregation.Values) this.properties.get(name); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponseGroup.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponseGroup.java index 08cb33146..8105b8830 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponseGroup.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/AggregateResponseGroup.java @@ -10,7 +10,7 @@ public boolean isText(String name) { } public TextAggregation.Values text(String name) { - checkPropertyType(name, this::isText, "Text"); + checkPropertyType(name, this::isText, "TEXT"); return (TextAggregation.Values) this.properties.get(name); } @@ -19,7 +19,7 @@ public boolean isInteger(String name) { } public IntegerAggregation.Values integer(String name) { - checkPropertyType(name, this::isInteger, "Integer"); + checkPropertyType(name, this::isInteger, "INTEGER"); return (IntegerAggregation.Values) this.properties.get(name); } @@ -28,7 +28,7 @@ public boolean isBool(String name) { } public BooleanAggregation.Values bool(String name) { - checkPropertyType(name, this::isBool, "Boolean"); + checkPropertyType(name, this::isBool, "BOOLEAN"); return (BooleanAggregation.Values) this.properties.get(name); } @@ -37,7 +37,7 @@ public boolean isDate(String name) { } public DateAggregation.Values date(String name) { - checkPropertyType(name, this::isDate, "Date"); + checkPropertyType(name, this::isDate, "DATE"); return (DateAggregation.Values) this.properties.get(name); } @@ -46,7 +46,7 @@ public boolean isNumber(String name) { } public NumberAggregation.Values number(String name) { - checkPropertyType(name, this::isNumber, "Number"); + checkPropertyType(name, this::isNumber, "NUMBER"); return (NumberAggregation.Values) this.properties.get(name); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java index 6a67d37db..e2c7d778e 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java @@ -8,7 +8,7 @@ public boolean isText() { } public String text() { - checkPropertyType(this::isText, "Text"); + checkPropertyType(this::isText, "TEXT"); return (String) value; } @@ -17,7 +17,7 @@ public boolean isInteger() { } public Long integer() { - checkPropertyType(this::isInteger, "Long"); + checkPropertyType(this::isInteger, "LONG"); return (Long) value; } @@ -26,7 +26,7 @@ public boolean isBool() { } public Boolean bool() { - checkPropertyType(this::isBool, "Boolean"); + checkPropertyType(this::isBool, "BOOLEAN"); return (Boolean) value; } @@ -35,7 +35,7 @@ public boolean isNumber() { } public Double number() { - checkPropertyType(this::isNumber, "Number"); + checkPropertyType(this::isNumber, "NUMBER"); return (Double) value; } From 4968774008b238339f4f661071ffa1edb1ec4569 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 25 Aug 2025 14:00:56 +0200 Subject: [PATCH 06/17] refactor: change Integer -> Long and Number -> Double in Where --- .../v1/api/collections/query/Where.java | 148 +++++++++--------- 1 file changed, 70 insertions(+), 78 deletions(-) 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 09c460acb..3aee7eabf 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 @@ -133,19 +133,19 @@ public Where eq(Boolean... values) { return new Where(Operator.EQUAL, left, new BooleanArrayOperand(values)); } - public Where eq(Integer value) { + public Where eq(Long value) { return new Where(Operator.EQUAL, left, new IntegerOperand(value)); } - public Where eq(Integer... values) { + public Where eq(Long... values) { return new Where(Operator.EQUAL, left, new IntegerArrayOperand(values)); } - public Where eq(Number value) { - return new Where(Operator.EQUAL, left, new NumberOperand(value.doubleValue())); + public Where eq(Double value) { + return new Where(Operator.EQUAL, left, new NumberOperand(value)); } - public Where eq(Number... values) { + public Where eq(Double... values) { return new Where(Operator.EQUAL, left, new NumberArrayOperand(values)); } @@ -179,19 +179,19 @@ public Where ne(Boolean... values) { return new Where(Operator.NOT_EQUAL, left, new BooleanArrayOperand(values)); } - public Where ne(Integer value) { + public Where ne(Long value) { return new Where(Operator.NOT_EQUAL, left, new IntegerOperand(value)); } - public Where ne(Integer... values) { + public Where ne(Long... values) { return new Where(Operator.NOT_EQUAL, left, new IntegerArrayOperand(values)); } - public Where ne(Number value) { - return new Where(Operator.NOT_EQUAL, left, new NumberOperand(value.doubleValue())); + public Where ne(Double value) { + return new Where(Operator.NOT_EQUAL, left, new NumberOperand(value)); } - public Where ne(Number... values) { + public Where ne(Double... values) { return new Where(Operator.NOT_EQUAL, left, new NumberArrayOperand(values)); } @@ -217,19 +217,19 @@ public Where lt(String... values) { return new Where(Operator.LESS_THAN, left, new TextArrayOperand(values)); } - public Where lt(Integer value) { + public Where lt(Long value) { return new Where(Operator.LESS_THAN, left, new IntegerOperand(value)); } - public Where lt(Integer... values) { + public Where lt(Long... values) { return new Where(Operator.LESS_THAN, left, new IntegerArrayOperand(values)); } - public Where lt(Number value) { - return new Where(Operator.LESS_THAN, left, new NumberOperand(value.doubleValue())); + public Where lt(Double value) { + return new Where(Operator.LESS_THAN, left, new NumberOperand(value)); } - public Where lt(Number... values) { + public Where lt(Double... values) { return new Where(Operator.LESS_THAN, left, new NumberArrayOperand(values)); } @@ -255,19 +255,19 @@ public Where lte(String... values) { return new Where(Operator.LESS_THAN_EQUAL, left, new TextArrayOperand(values)); } - public Where lte(Integer value) { + public Where lte(Long value) { return new Where(Operator.LESS_THAN_EQUAL, left, new IntegerOperand(value)); } - public Where lte(Integer... values) { + public Where lte(Long... values) { return new Where(Operator.LESS_THAN_EQUAL, left, new IntegerArrayOperand(values)); } - public Where lte(Number value) { - return new Where(Operator.LESS_THAN_EQUAL, left, new NumberOperand(value.doubleValue())); + public Where lte(Double value) { + return new Where(Operator.LESS_THAN_EQUAL, left, new NumberOperand(value)); } - public Where lte(Number... values) { + public Where lte(Double... values) { return new Where(Operator.LESS_THAN_EQUAL, left, new NumberArrayOperand(values)); } @@ -293,19 +293,19 @@ public Where gt(String... values) { return new Where(Operator.GREATER_THAN, left, new TextArrayOperand(values)); } - public Where gt(Integer value) { + public Where gt(Long value) { return new Where(Operator.GREATER_THAN, left, new IntegerOperand(value)); } - public Where gt(Integer... values) { + public Where gt(Long... values) { return new Where(Operator.GREATER_THAN, left, new IntegerArrayOperand(values)); } - public Where gt(Number value) { - return new Where(Operator.GREATER_THAN, left, new NumberOperand(value.doubleValue())); + public Where gt(Double value) { + return new Where(Operator.GREATER_THAN, left, new NumberOperand(value)); } - public Where gt(Number... values) { + public Where gt(Double... values) { return new Where(Operator.GREATER_THAN, left, new NumberArrayOperand(values)); } @@ -331,19 +331,19 @@ public Where gte(String... values) { return new Where(Operator.GREATER_THAN_EQUAL, left, new TextArrayOperand(values)); } - public Where gte(Integer value) { + public Where gte(Long value) { return new Where(Operator.GREATER_THAN_EQUAL, left, new IntegerOperand(value)); } - public Where gte(Integer... values) { + public Where gte(Long... values) { return new Where(Operator.GREATER_THAN_EQUAL, left, new IntegerArrayOperand(values)); } - public Where gte(Number value) { - return new Where(Operator.GREATER_THAN_EQUAL, left, new NumberOperand(value.doubleValue())); + public Where gte(Double value) { + return new Where(Operator.GREATER_THAN_EQUAL, left, new NumberOperand(value)); } - public Where gte(Number... values) { + public Where gte(Double... values) { return new Where(Operator.GREATER_THAN_EQUAL, left, new NumberArrayOperand(values)); } @@ -379,11 +379,11 @@ public Where containsAny(Boolean... values) { return new Where(Operator.CONTAINS_ANY, left, new BooleanArrayOperand(values)); } - public Where containsAny(Integer... values) { + public Where containsAny(Long... values) { return new Where(Operator.CONTAINS_ANY, left, new IntegerArrayOperand(values)); } - public Where containsAny(Number... values) { + public Where containsAny(Double... values) { return new Where(Operator.CONTAINS_ANY, left, new NumberArrayOperand(values)); } @@ -405,11 +405,11 @@ public Where containsAll(Boolean... values) { return new Where(Operator.CONTAINS_ALL, left, new BooleanArrayOperand(values)); } - public Where containsAll(Integer... values) { + public Where containsAll(Long... values) { return new Where(Operator.CONTAINS_ALL, left, new IntegerArrayOperand(values)); } - public Where containsAll(Number... values) { + public Where containsAll(Double... values) { return new Where(Operator.CONTAINS_ALL, left, new NumberArrayOperand(values)); } @@ -452,26 +452,26 @@ public void appendTo(WeaviateProtoBase.Filters.Builder where) { @SuppressWarnings("unchecked") static WhereOperand fromObject(Object value) { - if (value instanceof String) { - return new TextOperand((String) value); - } else if (value instanceof Boolean) { - return new BooleanOperand((Boolean) value); - } else if (value instanceof Integer) { - return new IntegerOperand((Integer) value); - } else if (value instanceof Number) { - return new NumberOperand((Number) 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 lng) { + return new IntegerOperand(lng); + } else if (value instanceof Double dbl) { + return new NumberOperand(dbl); } else if (value instanceof Date) { return new DateOperand((Date) value); - } else if (value instanceof String[]) { - return new TextArrayOperand((String[]) value); - } else if (value instanceof Boolean[]) { - return new BooleanArrayOperand((Boolean[]) value); - } else if (value instanceof Integer[]) { - return new IntegerArrayOperand((Integer[]) value); - } else if (value instanceof Number[]) { - return new NumberArrayOperand((Number[]) value); - } else if (value instanceof Date[]) { - return new DateArrayOperand((Date[]) value); + } 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 Date[] datearr) { + return new DateArrayOperand(datearr); } else if (value instanceof List) { if (((List) value).isEmpty()) { throw new IllegalArgumentException( @@ -483,16 +483,16 @@ static WhereOperand fromObject(Object value) { return new TextArrayOperand((List) value); } else if (first instanceof Boolean) { return new BooleanArrayOperand((List) value); - } else if (first instanceof Integer) { - return new IntegerArrayOperand((List) value); - } else if (first instanceof Number) { - return new NumberArrayOperand((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 Date) { return new DateArrayOperand((List) value); } } throw new IllegalArgumentException( - "value must be either of String, Boolean, Date, Integer, Number, Array/List of these types"); + "value must be either of String, Boolean, Date, Integer, Long, Double, Array/List of these types"); } private static class PathOperand implements WhereOperand { @@ -604,9 +604,9 @@ public String toString() { } private static class IntegerOperand implements WhereOperand { - private final Integer value; + private final Long value; - private IntegerOperand(Integer value) { + private IntegerOperand(Long value) { this.value = value; } @@ -622,24 +622,20 @@ public String toString() { } private static class IntegerArrayOperand implements WhereOperand { - private final List values; + private final List values; - private IntegerArrayOperand(List values) { + private IntegerArrayOperand(List values) { this.values = values; } @SafeVarargs - private IntegerArrayOperand(Integer... values) { + private IntegerArrayOperand(Long... values) { this(Arrays.asList(values)); } - private List toLongs() { - return values.stream().map(Integer::longValue).toList(); - } - @Override public void appendTo(WeaviateProtoBase.Filters.Builder where) { - where.setValueIntArray(WeaviateProtoBase.IntArray.newBuilder().addAllValues(toLongs())); + where.setValueIntArray(WeaviateProtoBase.IntArray.newBuilder().addAllValues(values)); } @Override @@ -649,15 +645,15 @@ public String toString() { } private static class NumberOperand implements WhereOperand { - private final Number value; + private final Double value; - private NumberOperand(Number value) { + private NumberOperand(Double value) { this.value = value; } @Override public void appendTo(WeaviateProtoBase.Filters.Builder where) { - where.setValueNumber(value.doubleValue()); + where.setValueNumber(value); } @Override @@ -667,24 +663,20 @@ public String toString() { } private static class NumberArrayOperand implements WhereOperand { - private final List values; + private final List values; - private NumberArrayOperand(List values) { + private NumberArrayOperand(List values) { this.values = values; } @SafeVarargs - private NumberArrayOperand(Number... values) { + private NumberArrayOperand(Double... values) { this(Arrays.asList(values)); } - private List toDoubles() { - return values.stream().map(Number::doubleValue).toList(); - } - @Override public void appendTo(WeaviateProtoBase.Filters.Builder where) { - where.setValueNumberArray(WeaviateProtoBase.NumberArray.newBuilder().addAllValues(toDoubles())); + where.setValueNumberArray(WeaviateProtoBase.NumberArray.newBuilder().addAllValues(values)); } @Override From 085e47ec5292e3e728f4e9ee838516b62086f54b Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 25 Aug 2025 14:06:25 +0200 Subject: [PATCH 07/17] refactor: use OffsetDateTime in Where --- .../v1/api/collections/query/Where.java | 64 +++++++++---------- 1 file changed, 29 insertions(+), 35 deletions(-) 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 3aee7eabf..7d0af64c0 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 @@ -1,11 +1,9 @@ package io.weaviate.client6.v1.api.collections.query; +import java.time.OffsetDateTime; import java.util.Arrays; -import java.util.Date; import java.util.List; -import org.apache.commons.lang3.time.DateFormatUtils; - import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBase; import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoBase.Filters; @@ -149,11 +147,11 @@ public Where eq(Double... values) { return new Where(Operator.EQUAL, left, new NumberArrayOperand(values)); } - public Where eq(Date value) { + public Where eq(OffsetDateTime value) { return new Where(Operator.EQUAL, left, new DateOperand(value)); } - public Where eq(Date... values) { + public Where eq(OffsetDateTime... values) { return new Where(Operator.EQUAL, left, new DateArrayOperand(values)); } @@ -195,11 +193,11 @@ public Where ne(Double... values) { return new Where(Operator.NOT_EQUAL, left, new NumberArrayOperand(values)); } - public Where ne(Date value) { + public Where ne(OffsetDateTime value) { return new Where(Operator.NOT_EQUAL, left, new DateOperand(value)); } - public Where ne(Date... values) { + public Where ne(OffsetDateTime... values) { return new Where(Operator.NOT_EQUAL, left, new DateArrayOperand(values)); } @@ -233,11 +231,11 @@ public Where lt(Double... values) { return new Where(Operator.LESS_THAN, left, new NumberArrayOperand(values)); } - public Where lt(Date value) { + public Where lt(OffsetDateTime value) { return new Where(Operator.LESS_THAN, left, new DateOperand(value)); } - public Where lt(Date... values) { + public Where lt(OffsetDateTime... values) { return new Where(Operator.LESS_THAN, left, new DateArrayOperand(values)); } @@ -271,11 +269,11 @@ public Where lte(Double... values) { return new Where(Operator.LESS_THAN_EQUAL, left, new NumberArrayOperand(values)); } - public Where lte(Date value) { + public Where lte(OffsetDateTime value) { return new Where(Operator.LESS_THAN_EQUAL, left, new DateOperand(value)); } - public Where lte(Date... values) { + public Where lte(OffsetDateTime... values) { return new Where(Operator.LESS_THAN_EQUAL, left, new DateArrayOperand(values)); } @@ -309,11 +307,11 @@ public Where gt(Double... values) { return new Where(Operator.GREATER_THAN, left, new NumberArrayOperand(values)); } - public Where gt(Date value) { + public Where gt(OffsetDateTime value) { return new Where(Operator.GREATER_THAN, left, new DateOperand(value)); } - public Where gt(Date... values) { + public Where gt(OffsetDateTime... values) { return new Where(Operator.GREATER_THAN, left, new DateArrayOperand(values)); } @@ -347,11 +345,11 @@ public Where gte(Double... values) { return new Where(Operator.GREATER_THAN_EQUAL, left, new NumberArrayOperand(values)); } - public Where gte(Date value) { + public Where gte(OffsetDateTime value) { return new Where(Operator.GREATER_THAN_EQUAL, left, new DateOperand(value)); } - public Where gte(Date... values) { + public Where gte(OffsetDateTime... values) { return new Where(Operator.GREATER_THAN_EQUAL, left, new DateArrayOperand(values)); } @@ -387,7 +385,7 @@ public Where containsAny(Double... values) { return new Where(Operator.CONTAINS_ANY, left, new NumberArrayOperand(values)); } - public Where containsAny(Date... values) { + public Where containsAny(OffsetDateTime... values) { return new Where(Operator.CONTAINS_ANY, left, new DateArrayOperand(values)); } @@ -413,7 +411,7 @@ public Where containsAll(Double... values) { return new Where(Operator.CONTAINS_ALL, left, new NumberArrayOperand(values)); } - public Where containsAll(Date... values) { + public Where containsAll(OffsetDateTime... values) { return new Where(Operator.CONTAINS_ALL, left, new DateArrayOperand(values)); } @@ -460,8 +458,8 @@ static WhereOperand fromObject(Object value) { return new IntegerOperand(lng); } else if (value instanceof Double dbl) { return new NumberOperand(dbl); - } else if (value instanceof Date) { - return new DateOperand((Date) value); + } 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) { @@ -470,7 +468,7 @@ static WhereOperand fromObject(Object value) { return new IntegerArrayOperand(lngarr); } else if (value instanceof Double[] dblarr) { return new NumberArrayOperand(dblarr); - } else if (value instanceof Date[] datearr) { + } else if (value instanceof OffsetDateTime[] datearr) { return new DateArrayOperand(datearr); } else if (value instanceof List) { if (((List) value).isEmpty()) { @@ -487,12 +485,12 @@ static WhereOperand fromObject(Object value) { return new IntegerArrayOperand((List) value); } else if (first instanceof Double) { return new NumberArrayOperand((List) value); - } else if (first instanceof Date) { - return new DateArrayOperand((List) value); + } else if (first instanceof OffsetDateTime) { + return new DateArrayOperand((List) value); } } throw new IllegalArgumentException( - "value must be either of String, Boolean, Date, Integer, Long, Double, Array/List of these types"); + "value must be either of String, Boolean, OffsetDateTime, Integer, Long, Double, Array/List of these types"); } private static class PathOperand implements WhereOperand { @@ -686,41 +684,37 @@ public String toString() { } private static class DateOperand implements WhereOperand { - private final Date value; + private final OffsetDateTime value; - private DateOperand(Date value) { + private DateOperand(OffsetDateTime value) { this.value = value; } - private static String format(Date date) { - return DateFormatUtils.format(date, "yyyy-MM-dd'T'HH:mm:ssZZZZZ"); - } - @Override public void appendTo(WeaviateProtoBase.Filters.Builder where) { - where.setValueText(format(value)); + where.setValueText(value.toString()); } @Override public String toString() { - return format(value); + return value.toString(); } } private static class DateArrayOperand implements WhereOperand { - private final List values; + private final List values; - private DateArrayOperand(List values) { + private DateArrayOperand(List values) { this.values = values; } @SafeVarargs - private DateArrayOperand(Date... values) { + private DateArrayOperand(OffsetDateTime... values) { this(Arrays.asList(values)); } private List formatted() { - return values.stream().map(date -> DateOperand.format(date)).toList(); + return values.stream().map(OffsetDateTime::toString).toList(); } @Override From 71350bfde283b1af3f69f33fcd83d32a79028531 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 25 Aug 2025 15:05:12 +0200 Subject: [PATCH 08/17] test: add test case for reading/writing all property types --- .../io/weaviate/integration/DataITest.java | 47 +++++++++++++++++++ .../client6/v1/api/collections/DataType.java | 4 +- .../client6/v1/internal/DateUtil.java | 37 +++++++++++++++ .../v1/internal/grpc/ByteStringUtil.java | 4 ++ .../client6/v1/internal/json/JSON.java | 2 + 5 files changed, 92 insertions(+), 2 deletions(-) diff --git a/src/it/java/io/weaviate/integration/DataITest.java b/src/it/java/io/weaviate/integration/DataITest.java index 22071e321..c4b53eb8e 100644 --- a/src/it/java/io/weaviate/integration/DataITest.java +++ b/src/it/java/io/weaviate/integration/DataITest.java @@ -1,7 +1,9 @@ package io.weaviate.integration; import java.io.IOException; +import java.time.OffsetDateTime; import java.util.Map; +import java.util.UUID; import org.assertj.core.api.Assertions; import org.assertj.core.api.InstanceOfAssertFactories; @@ -407,4 +409,49 @@ public void testDuplicateUuid() throws IOException { // Act things.data.insert(Map.of(), thing -> thing.uuid(thing_1.uuid())); } + + @Test + public void testDataTypes() throws IOException { + // Arrange + var nsDataTypes = ns("DataTypes"); + + // BLOB type is omitted because a base64-encoded image + // isn't doing the failure message any favours. + // It's tested in other test cases above. + client.collections.create( + nsDataTypes, c -> c + .properties( + Property.text("prop_text"), + Property.integer("prop_integer"), + Property.number("prop_number"), + Property.bool("prop_bool"), + Property.date("prop_date"), + Property.uuid("prop_uuid"))); + + var types = client.collections.use(nsDataTypes); + + var now = OffsetDateTime.now(); + var uuid = UUID.randomUUID(); + + Map want = Map.of( + "prop_text", "Hello, World!", + "prop_integer", 1L, + "prop_number", 1D, + "prop_bool", true, + "prop_date", now, + "prop_uuid", uuid); + var returnProperties = want.keySet().toArray(String[]::new); + + // Act + var object = types.data.insert(want); + var got = types.query.byId(object.uuid(), + q -> q.returnProperties(returnProperties)); + + // Assert + Assertions.assertThat(got).get() + .extracting(WeaviateObject::properties) + .asInstanceOf(InstanceOfAssertFactories.map(String.class, Object.class)) + .containsAllEntriesOf(want); + + } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java index 0e9027d41..45f079c13 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java @@ -7,11 +7,11 @@ public interface DataType { public static final String TEXT = "text"; public static final String INT = "int"; - public static final String BLOB = "blob"; + public static final String NUMBER = "number"; public static final String BOOL = "boolean"; + public static final String BLOB = "blob"; public static final String DATE = "date"; public static final String UUID = "uuid"; - public static final String NUMBER = "number"; public static final Set KNOWN_TYPES = ImmutableSet.of(TEXT, INT, BLOB, BOOL, DATE, UUID, NUMBER); } diff --git a/src/main/java/io/weaviate/client6/v1/internal/DateUtil.java b/src/main/java/io/weaviate/client6/v1/internal/DateUtil.java index c7433cd75..dbd432481 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/DateUtil.java +++ b/src/main/java/io/weaviate/client6/v1/internal/DateUtil.java @@ -1,11 +1,48 @@ package io.weaviate.client6.v1.internal; +import java.io.IOException; import java.time.OffsetDateTime; +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; + public final class DateUtil { + /** Prevent public initialization. */ + private DateUtil() { + } /** Convert ISO8601-formatted time string to {@Olink OffsetDateTime}. */ public static OffsetDateTime fromISO8601(String iso8601) { return OffsetDateTime.parse(iso8601); } + + public static enum CustomTypeAdapterFactory implements TypeAdapterFactory { + INSTANCE; + + @SuppressWarnings("unchecked") + @Override + public TypeAdapter create(Gson gson, TypeToken type) { + if (type.getRawType() != OffsetDateTime.class) { + return null; + } + + return (TypeAdapter) new TypeAdapter() { + + @Override + public void write(JsonWriter out, OffsetDateTime value) throws IOException { + out.value(value.toString()); + } + + @Override + public OffsetDateTime read(JsonReader in) throws IOException { + return OffsetDateTime.parse(in.nextString()); + } + + }.nullSafe(); + } + } } diff --git a/src/main/java/io/weaviate/client6/v1/internal/grpc/ByteStringUtil.java b/src/main/java/io/weaviate/client6/v1/internal/grpc/ByteStringUtil.java index 1d45bed0f..f7fc9fa12 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/grpc/ByteStringUtil.java +++ b/src/main/java/io/weaviate/client6/v1/internal/grpc/ByteStringUtil.java @@ -9,6 +9,10 @@ import com.google.protobuf.ByteString; public class ByteStringUtil { + /** Prevent public initialization. */ + private ByteStringUtil() { + } + private static final ByteOrder BYTE_ORDER = ByteOrder.LITTLE_ENDIAN; /** Decode ByteString to UUID. */ 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..a2cba568f 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 @@ -25,6 +25,8 @@ public final class JSON { io.weaviate.client6.v1.api.collections.Reranker.CustomTypeAdapterFactory.INSTANCE); gsonBuilder.registerTypeAdapterFactory( io.weaviate.client6.v1.api.collections.Generative.CustomTypeAdapterFactory.INSTANCE); + gsonBuilder.registerTypeAdapterFactory( + io.weaviate.client6.v1.internal.DateUtil.CustomTypeAdapterFactory.INSTANCE); // TypeAdapters ----------------------------------------------------------- gsonBuilder.registerTypeAdapter( From ff08558d19bf24064cb567e6eb5fe9bde00e5a21 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 25 Aug 2025 16:40:34 +0200 Subject: [PATCH 09/17] feat: add text[] data type --- src/it/java/io/weaviate/integration/DataITest.java | 7 +++++-- .../client6/v1/api/collections/DataType.java | 5 ++++- .../client6/v1/api/collections/Property.java | 8 ++++++++ .../v1/api/collections/aggregate/GroupedBy.java | 12 ++++++++++++ .../v1/api/collections/query/QueryRequest.java | 5 +++++ .../weaviate/client6/v1/internal/orm/MapBuilder.java | 6 ++++++ .../client6/v1/internal/orm/PropertiesBuilder.java | 5 ++++- 7 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/it/java/io/weaviate/integration/DataITest.java b/src/it/java/io/weaviate/integration/DataITest.java index c4b53eb8e..a8772d0fb 100644 --- a/src/it/java/io/weaviate/integration/DataITest.java +++ b/src/it/java/io/weaviate/integration/DataITest.java @@ -2,6 +2,7 @@ import java.io.IOException; import java.time.OffsetDateTime; +import java.util.List; import java.util.Map; import java.util.UUID; @@ -426,7 +427,8 @@ public void testDataTypes() throws IOException { Property.number("prop_number"), Property.bool("prop_bool"), Property.date("prop_date"), - Property.uuid("prop_uuid"))); + Property.uuid("prop_uuid"), + Property.textArray("prop_text_array"))); var types = client.collections.use(nsDataTypes); @@ -439,7 +441,8 @@ public void testDataTypes() throws IOException { "prop_number", 1D, "prop_bool", true, "prop_date", now, - "prop_uuid", uuid); + "prop_uuid", uuid, + "prop_text_array", List.of("a", "b", "c")); var returnProperties = want.keySet().toArray(String[]::new); // Act diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java index 45f079c13..b441cc0a3 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java @@ -6,6 +6,7 @@ public interface DataType { public static final String TEXT = "text"; + public static final String TEXT_ARRAY = "text[]"; public static final String INT = "int"; public static final String NUMBER = "number"; public static final String BOOL = "boolean"; @@ -13,5 +14,7 @@ public interface DataType { public static final String DATE = "date"; public static final String UUID = "uuid"; - public static final Set KNOWN_TYPES = ImmutableSet.of(TEXT, INT, BLOB, BOOL, DATE, UUID, NUMBER); + public static final Set KNOWN_TYPES = ImmutableSet.of( + TEXT, INT, BLOB, BOOL, DATE, UUID, NUMBER, + TEXT_ARRAY); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/Property.java b/src/main/java/io/weaviate/client6/v1/api/collections/Property.java index b1458c4bd..f857b3779 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/Property.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/Property.java @@ -27,6 +27,14 @@ public static Property text(String name, Function> fn) { + return newProperty(name, DataType.TEXT_ARRAY, fn); + } + public static Property integer(String name) { return integer(name, ObjectBuilder.identity()); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java index e2c7d778e..cbf23d834 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java @@ -1,5 +1,7 @@ package io.weaviate.client6.v1.api.collections.aggregate; +import java.util.Arrays; +import java.util.List; import java.util.function.Supplier; public record GroupedBy(String property, T value) { @@ -39,6 +41,16 @@ public Double number() { return (Double) value; } + public boolean isTextArray() { + return value instanceof String[]; + } + + @SuppressWarnings("unchecked") + public List textArray() { + checkPropertyType(this::isTextArray, "NUMBER"); + return (List) Arrays.asList(value); + } + private void checkPropertyType(Supplier check, String expected) { if (!check.get()) { throw new IllegalStateException(property + "is not a " + expected + " property"); 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 264356402..8a49d1725 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 @@ -210,6 +210,11 @@ private static void setProperty(String property, WeaviateProtoProperties.Val builder.setOffsetDateTime(property, DateUtil.fromISO8601(value.getDateValue())); } else if (value.hasUuidValue()) { builder.setUuid(property, UUID.fromString(value.getUuidValue())); + } else if (value.hasListValue()) { + var list = value.getListValue(); + if (list.hasTextValues()) { + builder.setTextArray(property, list.getTextValues().getValuesList()); + } } else { assert false : "(query) branch not covered"; } diff --git a/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java b/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java index 83581e193..ed655d29c 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java +++ b/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java @@ -2,6 +2,7 @@ import java.time.OffsetDateTime; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; @@ -48,6 +49,11 @@ public void setUuid(String property, UUID value) { properties.put(property, value); } + @Override + public void setTextArray(String property, List value) { + properties.put(property, value); + } + @Override public Map build() { return properties; diff --git a/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java b/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java index 561bd677e..2b43752de 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java +++ b/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java @@ -1,6 +1,7 @@ package io.weaviate.client6.v1.internal.orm; import java.time.OffsetDateTime; +import java.util.List; import java.util.UUID; public interface PropertiesBuilder { @@ -18,7 +19,9 @@ public interface PropertiesBuilder { void setOffsetDateTime(String property, OffsetDateTime value); - void setUuid(String property, UUID uuid); + void setUuid(String property, UUID value); + + void setTextArray(String property, List value); T build(); } From 236b047b69d92c5f9d5f5089496558a2c723d6fa Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 25 Aug 2025 16:49:09 +0200 Subject: [PATCH 10/17] feat: add uuid[] data type --- src/it/java/io/weaviate/integration/DataITest.java | 2 ++ .../io/weaviate/client6/v1/api/collections/DataType.java | 3 ++- .../io/weaviate/client6/v1/api/collections/Property.java | 8 ++++++++ .../client6/v1/api/collections/query/QueryRequest.java | 4 ++++ .../io/weaviate/client6/v1/internal/orm/MapBuilder.java | 5 +++++ .../client6/v1/internal/orm/PropertiesBuilder.java | 2 ++ 6 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/it/java/io/weaviate/integration/DataITest.java b/src/it/java/io/weaviate/integration/DataITest.java index a8772d0fb..5866e4691 100644 --- a/src/it/java/io/weaviate/integration/DataITest.java +++ b/src/it/java/io/weaviate/integration/DataITest.java @@ -428,6 +428,7 @@ public void testDataTypes() throws IOException { Property.bool("prop_bool"), Property.date("prop_date"), Property.uuid("prop_uuid"), + Property.uuidArray("prop_uuid_array"), Property.textArray("prop_text_array"))); var types = client.collections.use(nsDataTypes); @@ -442,6 +443,7 @@ public void testDataTypes() throws IOException { "prop_bool", true, "prop_date", now, "prop_uuid", uuid, + "prop_uuid_array", List.of(uuid, uuid), "prop_text_array", List.of("a", "b", "c")); var returnProperties = want.keySet().toArray(String[]::new); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java index b441cc0a3..d64502c78 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java @@ -13,8 +13,9 @@ public interface DataType { public static final String BLOB = "blob"; public static final String DATE = "date"; public static final String UUID = "uuid"; + public static final String UUID_ARRAY = "uuid[]"; public static final Set KNOWN_TYPES = ImmutableSet.of( TEXT, INT, BLOB, BOOL, DATE, UUID, NUMBER, - TEXT_ARRAY); + TEXT_ARRAY, UUID_ARRAY); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/Property.java b/src/main/java/io/weaviate/client6/v1/api/collections/Property.java index f857b3779..0f18be89b 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/Property.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/Property.java @@ -75,6 +75,14 @@ public static Property uuid(String name, Function> fn) { + return newProperty(name, DataType.UUID_ARRAY, fn); + } + public static Property number(String name) { return number(name, ObjectBuilder.identity()); } 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 8a49d1725..5705d0848 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 @@ -214,6 +214,10 @@ private static void setProperty(String property, WeaviateProtoProperties.Val var list = value.getListValue(); if (list.hasTextValues()) { builder.setTextArray(property, list.getTextValues().getValuesList()); + } else if (list.hasUuidValues()) { + var uuids = list.getUuidValues().getValuesList().stream() + .map(UUID::fromString).toList(); + builder.setUuidArray(property, uuids); } } else { assert false : "(query) branch not covered"; diff --git a/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java b/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java index ed655d29c..cd9377719 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java +++ b/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java @@ -54,6 +54,11 @@ public void setTextArray(String property, List value) { properties.put(property, value); } + @Override + public void setUuidArray(String property, List value) { + properties.put(property, value); + } + @Override public Map build() { return properties; diff --git a/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java b/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java index 2b43752de..e5642d498 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java +++ b/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java @@ -23,5 +23,7 @@ public interface PropertiesBuilder { void setTextArray(String property, List value); + void setUuidArray(String property, List value); + T build(); } From 85490b62c1539db263e5a49881e75bcda95c70a5 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 25 Aug 2025 16:57:44 +0200 Subject: [PATCH 11/17] feat: add bool[] data type --- src/it/java/io/weaviate/integration/DataITest.java | 2 ++ .../client6/v1/api/collections/DataType.java | 3 ++- .../client6/v1/api/collections/Property.java | 8 ++++++++ .../api/collections/aggregate/AggregateRequest.java | 12 ++++++++---- .../v1/api/collections/aggregate/GroupedBy.java | 12 +++++++++++- .../v1/api/collections/query/QueryRequest.java | 2 ++ .../weaviate/client6/v1/internal/orm/MapBuilder.java | 5 +++++ .../client6/v1/internal/orm/PropertiesBuilder.java | 2 ++ 8 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/it/java/io/weaviate/integration/DataITest.java b/src/it/java/io/weaviate/integration/DataITest.java index 5866e4691..99a714e7d 100644 --- a/src/it/java/io/weaviate/integration/DataITest.java +++ b/src/it/java/io/weaviate/integration/DataITest.java @@ -428,6 +428,7 @@ public void testDataTypes() throws IOException { Property.bool("prop_bool"), Property.date("prop_date"), Property.uuid("prop_uuid"), + Property.boolArray("prop_bool_array"), Property.uuidArray("prop_uuid_array"), Property.textArray("prop_text_array"))); @@ -443,6 +444,7 @@ public void testDataTypes() throws IOException { "prop_bool", true, "prop_date", now, "prop_uuid", uuid, + "prop_bool_array", List.of(true, false), "prop_uuid_array", List.of(uuid, uuid), "prop_text_array", List.of("a", "b", "c")); var returnProperties = want.keySet().toArray(String[]::new); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java index d64502c78..1d50c9986 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java @@ -10,6 +10,7 @@ public interface DataType { public static final String INT = "int"; public static final String NUMBER = "number"; public static final String BOOL = "boolean"; + public static final String BOOL_ARRAY = "boolean[]"; public static final String BLOB = "blob"; public static final String DATE = "date"; public static final String UUID = "uuid"; @@ -17,5 +18,5 @@ public interface DataType { public static final Set KNOWN_TYPES = ImmutableSet.of( TEXT, INT, BLOB, BOOL, DATE, UUID, NUMBER, - TEXT_ARRAY, UUID_ARRAY); + TEXT_ARRAY, BOOL_ARRAY, UUID_ARRAY); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/Property.java b/src/main/java/io/weaviate/client6/v1/api/collections/Property.java index 0f18be89b..bbcb16ae6 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/Property.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/Property.java @@ -59,6 +59,14 @@ public static Property bool(String name, Function> fn) { + return newProperty(name, DataType.BOOL_ARRAY, fn); + } + public static Property date(String name) { return date(name, ObjectBuilder.identity()); } 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 7fb57895d..1a1d4c2c1 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 @@ -57,13 +57,17 @@ static Rpc(property, groupBy.getInt()); + groupedBy = new GroupedBy<>(property, groupBy.getInt()); } else if (groupBy.hasText()) { - groupedBy = new GroupedBy(property, groupBy.getText()); + groupedBy = new GroupedBy<>(property, groupBy.getText()); } else if (groupBy.hasBoolean()) { - groupedBy = new GroupedBy(property, groupBy.getBoolean()); + groupedBy = new GroupedBy<>(property, groupBy.getBoolean()); } else if (groupBy.hasNumber()) { - groupedBy = new GroupedBy(property, groupBy.getNumber()); + groupedBy = new GroupedBy<>(property, groupBy.getNumber()); + } else if (groupBy.hasTexts()) { + groupedBy = new GroupedBy<>(property, groupBy.getTexts().getValuesList().toArray(String[]::new)); + } else if (groupBy.hasBooleans()) { + groupedBy = new GroupedBy<>(property, groupBy.getBooleans().getValuesList().toArray(Boolean[]::new)); } else { assert false : "(aggregate) branch not covered"; } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java index cbf23d834..8450efd43 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java @@ -47,10 +47,20 @@ public boolean isTextArray() { @SuppressWarnings("unchecked") public List textArray() { - checkPropertyType(this::isTextArray, "NUMBER"); + checkPropertyType(this::isTextArray, "TEXT[]"); return (List) Arrays.asList(value); } + public boolean isBoolArray() { + return value instanceof Boolean[]; + } + + @SuppressWarnings("unchecked") + public List boolArray() { + checkPropertyType(this::isBoolArray, "BOOLEAN[]"); + return (List) Arrays.asList(value); + } + private void checkPropertyType(Supplier check, String expected) { if (!check.get()) { throw new IllegalStateException(property + "is not a " + expected + " property"); 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 5705d0848..ebf8713c9 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 @@ -218,6 +218,8 @@ private static void setProperty(String property, WeaviateProtoProperties.Val var uuids = list.getUuidValues().getValuesList().stream() .map(UUID::fromString).toList(); builder.setUuidArray(property, uuids); + } else if (list.hasBoolValues()) { + builder.setBooleanArray(property, list.getBoolValues().getValuesList()); } } else { assert false : "(query) branch not covered"; diff --git a/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java b/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java index cd9377719..3084089ed 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java +++ b/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java @@ -59,6 +59,11 @@ public void setUuidArray(String property, List value) { properties.put(property, value); } + @Override + public void setBooleanArray(String property, List value) { + properties.put(property, value); + } + @Override public Map build() { return properties; diff --git a/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java b/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java index e5642d498..7c358af61 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java +++ b/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java @@ -25,5 +25,7 @@ public interface PropertiesBuilder { void setUuidArray(String property, List value); + void setBooleanArray(String property, List value); + T build(); } From a725547e2f74532d8a87c6a58db6442a71787418 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 25 Aug 2025 17:03:55 +0200 Subject: [PATCH 12/17] feat: add date[] data type --- src/it/java/io/weaviate/integration/DataITest.java | 2 ++ .../io/weaviate/client6/v1/api/collections/DataType.java | 3 ++- .../io/weaviate/client6/v1/api/collections/Property.java | 8 ++++++++ .../client6/v1/api/collections/query/QueryRequest.java | 4 ++++ .../io/weaviate/client6/v1/internal/orm/MapBuilder.java | 5 +++++ .../client6/v1/internal/orm/PropertiesBuilder.java | 2 ++ 6 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/it/java/io/weaviate/integration/DataITest.java b/src/it/java/io/weaviate/integration/DataITest.java index 99a714e7d..48e6f2c87 100644 --- a/src/it/java/io/weaviate/integration/DataITest.java +++ b/src/it/java/io/weaviate/integration/DataITest.java @@ -429,6 +429,7 @@ public void testDataTypes() throws IOException { Property.date("prop_date"), Property.uuid("prop_uuid"), Property.boolArray("prop_bool_array"), + Property.dateArray("prop_date_array"), Property.uuidArray("prop_uuid_array"), Property.textArray("prop_text_array"))); @@ -445,6 +446,7 @@ public void testDataTypes() throws IOException { "prop_date", now, "prop_uuid", uuid, "prop_bool_array", List.of(true, false), + "prop_date_array", List.of(now, now), "prop_uuid_array", List.of(uuid, uuid), "prop_text_array", List.of("a", "b", "c")); var returnProperties = want.keySet().toArray(String[]::new); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java index 1d50c9986..9c690737f 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java @@ -13,10 +13,11 @@ public interface DataType { public static final String BOOL_ARRAY = "boolean[]"; public static final String BLOB = "blob"; public static final String DATE = "date"; + public static final String DATE_ARRAY = "date[]"; public static final String UUID = "uuid"; public static final String UUID_ARRAY = "uuid[]"; public static final Set KNOWN_TYPES = ImmutableSet.of( TEXT, INT, BLOB, BOOL, DATE, UUID, NUMBER, - TEXT_ARRAY, BOOL_ARRAY, UUID_ARRAY); + TEXT_ARRAY, BOOL_ARRAY, DATE_ARRAY, UUID_ARRAY); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/Property.java b/src/main/java/io/weaviate/client6/v1/api/collections/Property.java index bbcb16ae6..459e67c57 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/Property.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/Property.java @@ -75,6 +75,14 @@ public static Property date(String name, Function> fn) { + return newProperty(name, DataType.DATE_ARRAY, fn); + } + public static Property uuid(String name) { return uuid(name, ObjectBuilder.identity()); } 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 ebf8713c9..6b6aa4ceb 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 @@ -220,6 +220,10 @@ private static void setProperty(String property, WeaviateProtoProperties.Val builder.setUuidArray(property, uuids); } else if (list.hasBoolValues()) { builder.setBooleanArray(property, list.getBoolValues().getValuesList()); + } else if (list.hasDateValues()) { + var dates = list.getDateValues().getValuesList().stream() + .map(DateUtil::fromISO8601).toList(); + builder.setOffsetDateTimeArray(property, dates); } } else { assert false : "(query) branch not covered"; diff --git a/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java b/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java index 3084089ed..cb2759bc2 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java +++ b/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java @@ -64,6 +64,11 @@ public void setBooleanArray(String property, List value) { properties.put(property, value); } + @Override + public void setOffsetDateTimeArray(String property, List value) { + properties.put(property, value); + } + @Override public Map build() { return properties; diff --git a/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java b/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java index 7c358af61..ae58693fa 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java +++ b/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java @@ -27,5 +27,7 @@ public interface PropertiesBuilder { void setBooleanArray(String property, List value); + void setOffsetDateTimeArray(String property, List value); + T build(); } From f1ccf4965c574e82f177d36e0585d21594b58e1e Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 25 Aug 2025 17:37:15 +0200 Subject: [PATCH 13/17] feat: add integer[] data type --- .../io/weaviate/integration/DataITest.java | 24 ++++++++++--------- .../client6/v1/api/collections/DataType.java | 3 ++- .../client6/v1/api/collections/Property.java | 8 +++++++ .../aggregate/AggregateRequest.java | 2 ++ .../api/collections/aggregate/GroupedBy.java | 12 +++++++++- .../api/collections/query/QueryRequest.java | 6 +++++ .../v1/internal/grpc/ByteStringUtil.java | 16 +++++++++++++ .../client6/v1/internal/orm/MapBuilder.java | 5 ++++ .../v1/internal/orm/PropertiesBuilder.java | 2 ++ .../v1/internal/grpc/ByteStringUtilTest.java | 16 ++++++++++++- 10 files changed, 80 insertions(+), 14 deletions(-) diff --git a/src/it/java/io/weaviate/integration/DataITest.java b/src/it/java/io/weaviate/integration/DataITest.java index 48e6f2c87..226096d78 100644 --- a/src/it/java/io/weaviate/integration/DataITest.java +++ b/src/it/java/io/weaviate/integration/DataITest.java @@ -428,6 +428,7 @@ public void testDataTypes() throws IOException { Property.bool("prop_bool"), Property.date("prop_date"), Property.uuid("prop_uuid"), + Property.integerArray("prop_integer_array"), Property.boolArray("prop_bool_array"), Property.dateArray("prop_date_array"), Property.uuidArray("prop_uuid_array"), @@ -438,17 +439,18 @@ public void testDataTypes() throws IOException { var now = OffsetDateTime.now(); var uuid = UUID.randomUUID(); - Map want = Map.of( - "prop_text", "Hello, World!", - "prop_integer", 1L, - "prop_number", 1D, - "prop_bool", true, - "prop_date", now, - "prop_uuid", uuid, - "prop_bool_array", List.of(true, false), - "prop_date_array", List.of(now, now), - "prop_uuid_array", List.of(uuid, uuid), - "prop_text_array", List.of("a", "b", "c")); + Map want = Map.ofEntries( + Map.entry("prop_text", "Hello, World!"), + Map.entry("prop_integer", 1L), + Map.entry("prop_number", 1D), + Map.entry("prop_bool", true), + Map.entry("prop_date", now), + Map.entry("prop_uuid", uuid), + Map.entry("prop_integer_array", List.of(1L, 2L, 3L)), + Map.entry("prop_bool_array", List.of(true, false)), + Map.entry("prop_date_array", List.of(now, now)), + Map.entry("prop_uuid_array", List.of(uuid, uuid)), + Map.entry("prop_text_array", List.of("a", "b", "c"))); var returnProperties = want.keySet().toArray(String[]::new); // Act diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java index 9c690737f..27c95fc5b 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java @@ -8,6 +8,7 @@ public interface DataType { public static final String TEXT = "text"; public static final String TEXT_ARRAY = "text[]"; public static final String INT = "int"; + public static final String INT_ARRAY = "int[]"; public static final String NUMBER = "number"; public static final String BOOL = "boolean"; public static final String BOOL_ARRAY = "boolean[]"; @@ -19,5 +20,5 @@ public interface DataType { public static final Set KNOWN_TYPES = ImmutableSet.of( TEXT, INT, BLOB, BOOL, DATE, UUID, NUMBER, - TEXT_ARRAY, BOOL_ARRAY, DATE_ARRAY, UUID_ARRAY); + TEXT_ARRAY, INT_ARRAY, BOOL_ARRAY, DATE_ARRAY, UUID_ARRAY); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/Property.java b/src/main/java/io/weaviate/client6/v1/api/collections/Property.java index 459e67c57..6b9dbdb25 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/Property.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/Property.java @@ -43,6 +43,14 @@ public static Property integer(String name, Function> fn) { + return newProperty(name, DataType.INT_ARRAY, fn); + } + public static Property blob(String name) { return blob(name, ObjectBuilder.identity()); } 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 1a1d4c2c1..f89ea49f0 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 @@ -66,6 +66,8 @@ static Rpc(property, groupBy.getNumber()); } else if (groupBy.hasTexts()) { groupedBy = new GroupedBy<>(property, groupBy.getTexts().getValuesList().toArray(String[]::new)); + } else if (groupBy.hasInts()) { + groupedBy = new GroupedBy<>(property, groupBy.getInts().getValuesList().toArray(Long[]::new)); } else if (groupBy.hasBooleans()) { groupedBy = new GroupedBy<>(property, groupBy.getBooleans().getValuesList().toArray(Boolean[]::new)); } else { diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java index 8450efd43..48602137e 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java @@ -19,7 +19,7 @@ public boolean isInteger() { } public Long integer() { - checkPropertyType(this::isInteger, "LONG"); + checkPropertyType(this::isInteger, "INTEGER"); return (Long) value; } @@ -61,6 +61,16 @@ public List boolArray() { return (List) Arrays.asList(value); } + public boolean isIntegerArray() { + return value instanceof Long[]; + } + + @SuppressWarnings("unchecked") + public List integerArray() { + checkPropertyType(this::isIntegerArray, "INTEGER[]"); + return (List) Arrays.asList(value); + } + private void checkPropertyType(Supplier check, String expected) { if (!check.get()) { throw new IllegalStateException(property + "is not a " + expected + " property"); 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 6b6aa4ceb..ac035d58b 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 @@ -1,6 +1,7 @@ package io.weaviate.client6.v1.api.collections.query; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.UUID; @@ -214,6 +215,11 @@ private static void setProperty(String property, WeaviateProtoProperties.Val var list = value.getListValue(); if (list.hasTextValues()) { builder.setTextArray(property, list.getTextValues().getValuesList()); + } else if (list.hasIntValues()) { + var ints = Arrays.stream( + ByteStringUtil.decodeIntValues(list.getIntValues().getValues())) + .boxed().toList(); + builder.setLongArray(property, ints); } else if (list.hasUuidValues()) { var uuids = list.getUuidValues().getValuesList().stream() .map(UUID::fromString).toList(); diff --git a/src/main/java/io/weaviate/client6/v1/internal/grpc/ByteStringUtil.java b/src/main/java/io/weaviate/client6/v1/internal/grpc/ByteStringUtil.java index f7fc9fa12..3b8354447 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/grpc/ByteStringUtil.java +++ b/src/main/java/io/weaviate/client6/v1/internal/grpc/ByteStringUtil.java @@ -116,4 +116,20 @@ public static float[][] decodeVectorMulti(ByteString bs) { } return vectors; } + + /** + * Decode ByteString to {@code long[]}. + * + * @throws IllegalArgumentException if ByteString size is not + * a multiple of {@link Long#BYTES}. + */ + public static long[] decodeIntValues(ByteString bs) { + if (bs.size() % Long.BYTES != 0) { + throw new IllegalArgumentException( + "ByteString size " + bs.size() + " is not a multiple of " + String.valueOf(Long.BYTES) + " (Long.BYTES)"); + } + long[] vector = new long[bs.size() / Long.BYTES]; + bs.asReadOnlyByteBuffer().order(BYTE_ORDER).asLongBuffer().get(vector); + return vector; + } } diff --git a/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java b/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java index cb2759bc2..4cacfc60d 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java +++ b/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java @@ -54,6 +54,11 @@ public void setTextArray(String property, List value) { properties.put(property, value); } + @Override + public void setLongArray(String property, List value) { + properties.put(property, value); + } + @Override public void setUuidArray(String property, List value) { properties.put(property, value); diff --git a/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java b/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java index ae58693fa..72b175d31 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java +++ b/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java @@ -23,6 +23,8 @@ public interface PropertiesBuilder { void setTextArray(String property, List value); + void setLongArray(String property, List value); + void setUuidArray(String property, List value); void setBooleanArray(String property, List value); diff --git a/src/test/java/io/weaviate/client6/v1/internal/grpc/ByteStringUtilTest.java b/src/test/java/io/weaviate/client6/v1/internal/grpc/ByteStringUtilTest.java index f9c6d1f71..603dcb174 100644 --- a/src/test/java/io/weaviate/client6/v1/internal/grpc/ByteStringUtilTest.java +++ b/src/test/java/io/weaviate/client6/v1/internal/grpc/ByteStringUtilTest.java @@ -71,11 +71,19 @@ public void test_decodeVector_2d_empty() { @Test public void test_decodeVector_2d_dim_zero() { - byte[] bytes = new byte[] { 0, 0 }; + byte[] bytes = { 0, 0 }; float[][] got = ByteStringUtil.decodeVectorMulti(ByteString.copyFrom(bytes)); assertEquals(0, got.length); } + @Test + public void test_decodeIntValues() { + byte[] bytes = { 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0 }; + long[] want = { 1, 2, 3 }; + long[] got = ByteStringUtil.decodeIntValues(ByteString.copyFrom(bytes)); + assertArrayEquals(want, got); + } + @Test(expected = IllegalArgumentException.class) public void test_decodeVector_1d_illegal() { byte[] bytes = new byte[Float.BYTES - 1]; // must be a multiple of Float.BYTES @@ -93,4 +101,10 @@ public void test_decodeVector_2d_illegal() { ByteStringUtil.decodeVectorMulti(ByteString.copyFrom(bytes)); } + + @Test(expected = IllegalArgumentException.class) + public void test_decodeIntValues_illegal() { + byte[] bytes = new byte[Long.BYTES - 1]; // must be a multiple of Long.BYTES + ByteStringUtil.decodeIntValues(ByteString.copyFrom(bytes)); + } } From 5c1ab617699f720bcf7771e3bd989669027c5414 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 25 Aug 2025 17:55:23 +0200 Subject: [PATCH 14/17] feat: add number[] data type --- .../java/io/weaviate/integration/DataITest.java | 2 ++ .../client6/v1/api/collections/DataType.java | 3 ++- .../client6/v1/api/collections/Property.java | 8 ++++++++ .../collections/aggregate/AggregateRequest.java | 2 ++ .../v1/api/collections/aggregate/GroupedBy.java | 10 ++++++++++ .../v1/api/collections/query/QueryRequest.java | 5 +++++ .../client6/v1/internal/grpc/ByteStringUtil.java | 16 ++++++++++++++++ .../client6/v1/internal/orm/MapBuilder.java | 5 +++++ .../v1/internal/orm/PropertiesBuilder.java | 2 ++ .../v1/internal/grpc/ByteStringUtilTest.java | 15 +++++++++++++++ 10 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/it/java/io/weaviate/integration/DataITest.java b/src/it/java/io/weaviate/integration/DataITest.java index 226096d78..cac817c17 100644 --- a/src/it/java/io/weaviate/integration/DataITest.java +++ b/src/it/java/io/weaviate/integration/DataITest.java @@ -429,6 +429,7 @@ public void testDataTypes() throws IOException { Property.date("prop_date"), Property.uuid("prop_uuid"), Property.integerArray("prop_integer_array"), + Property.numberArray("prop_number_array"), Property.boolArray("prop_bool_array"), Property.dateArray("prop_date_array"), Property.uuidArray("prop_uuid_array"), @@ -447,6 +448,7 @@ public void testDataTypes() throws IOException { Map.entry("prop_date", now), Map.entry("prop_uuid", uuid), Map.entry("prop_integer_array", List.of(1L, 2L, 3L)), + Map.entry("prop_number_array", List.of(1D, 2D, 3D)), Map.entry("prop_bool_array", List.of(true, false)), Map.entry("prop_date_array", List.of(now, now)), Map.entry("prop_uuid_array", List.of(uuid, uuid)), diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java index 27c95fc5b..32858bca6 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/DataType.java @@ -10,6 +10,7 @@ public interface DataType { public static final String INT = "int"; public static final String INT_ARRAY = "int[]"; public static final String NUMBER = "number"; + public static final String NUMBER_ARRAY = "number[]"; public static final String BOOL = "boolean"; public static final String BOOL_ARRAY = "boolean[]"; public static final String BLOB = "blob"; @@ -20,5 +21,5 @@ public interface DataType { public static final Set KNOWN_TYPES = ImmutableSet.of( TEXT, INT, BLOB, BOOL, DATE, UUID, NUMBER, - TEXT_ARRAY, INT_ARRAY, BOOL_ARRAY, DATE_ARRAY, UUID_ARRAY); + TEXT_ARRAY, INT_ARRAY, NUMBER_ARRAY, BOOL_ARRAY, DATE_ARRAY, UUID_ARRAY); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/Property.java b/src/main/java/io/weaviate/client6/v1/api/collections/Property.java index 6b9dbdb25..13cde9536 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/Property.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/Property.java @@ -115,6 +115,14 @@ public static Property number(String name, Function> fn) { + return newProperty(name, DataType.NUMBER_ARRAY, fn); + } + private static Property newProperty(String name, String dataType, Function> fn) { return fn.apply(new Builder(name, dataType)).build(); } 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 f89ea49f0..9811c0601 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 @@ -68,6 +68,8 @@ static Rpc(property, groupBy.getTexts().getValuesList().toArray(String[]::new)); } else if (groupBy.hasInts()) { groupedBy = new GroupedBy<>(property, groupBy.getInts().getValuesList().toArray(Long[]::new)); + } else if (groupBy.hasNumbers()) { + groupedBy = new GroupedBy<>(property, groupBy.getNumbers().getValuesList().toArray(Double[]::new)); } else if (groupBy.hasBooleans()) { groupedBy = new GroupedBy<>(property, groupBy.getBooleans().getValuesList().toArray(Boolean[]::new)); } else { diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java index 48602137e..d17a0d218 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/GroupedBy.java @@ -71,6 +71,16 @@ public List integerArray() { return (List) Arrays.asList(value); } + public boolean isNumberArray() { + return value instanceof Double[]; + } + + @SuppressWarnings("unchecked") + public List numberArray() { + checkPropertyType(this::isNumberArray, "NUMBER[]"); + return (List) Arrays.asList(value); + } + private void checkPropertyType(Supplier check, String expected) { if (!check.get()) { throw new IllegalStateException(property + "is not a " + expected + " property"); 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 ac035d58b..199eccd4d 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 @@ -220,6 +220,11 @@ private static void setProperty(String property, WeaviateProtoProperties.Val ByteStringUtil.decodeIntValues(list.getIntValues().getValues())) .boxed().toList(); builder.setLongArray(property, ints); + } else if (list.hasNumberValues()) { + var numbers = Arrays.stream( + ByteStringUtil.decodeNumberValues(list.getNumberValues().getValues())) + .boxed().toList(); + builder.setDoubleArray(property, numbers); } else if (list.hasUuidValues()) { var uuids = list.getUuidValues().getValuesList().stream() .map(UUID::fromString).toList(); diff --git a/src/main/java/io/weaviate/client6/v1/internal/grpc/ByteStringUtil.java b/src/main/java/io/weaviate/client6/v1/internal/grpc/ByteStringUtil.java index 3b8354447..6bee6de0a 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/grpc/ByteStringUtil.java +++ b/src/main/java/io/weaviate/client6/v1/internal/grpc/ByteStringUtil.java @@ -132,4 +132,20 @@ public static long[] decodeIntValues(ByteString bs) { bs.asReadOnlyByteBuffer().order(BYTE_ORDER).asLongBuffer().get(vector); return vector; } + + /** + * Decode ByteString to {@code double[]}. + * + * @throws IllegalArgumentException if ByteString size is not + * a multiple of {@link Double#BYTES}. + */ + public static double[] decodeNumberValues(ByteString bs) { + if (bs.size() % Double.BYTES != 0) { + throw new IllegalArgumentException( + "ByteString size " + bs.size() + " is not a multiple of " + String.valueOf(Double.BYTES) + " (Double.BYTES)"); + } + double[] vector = new double[bs.size() / Double.BYTES]; + bs.asReadOnlyByteBuffer().order(BYTE_ORDER).asDoubleBuffer().get(vector); + return vector; + } } diff --git a/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java b/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java index 4cacfc60d..0e2c94c99 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java +++ b/src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java @@ -59,6 +59,11 @@ public void setLongArray(String property, List value) { properties.put(property, value); } + @Override + public void setDoubleArray(String property, List value) { + properties.put(property, value); + } + @Override public void setUuidArray(String property, List value) { properties.put(property, value); diff --git a/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java b/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java index 72b175d31..dd46f87c9 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java +++ b/src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java @@ -25,6 +25,8 @@ public interface PropertiesBuilder { void setLongArray(String property, List value); + void setDoubleArray(String property, List value); + void setUuidArray(String property, List value); void setBooleanArray(String property, List value); diff --git a/src/test/java/io/weaviate/client6/v1/internal/grpc/ByteStringUtilTest.java b/src/test/java/io/weaviate/client6/v1/internal/grpc/ByteStringUtilTest.java index 603dcb174..382dd9212 100644 --- a/src/test/java/io/weaviate/client6/v1/internal/grpc/ByteStringUtilTest.java +++ b/src/test/java/io/weaviate/client6/v1/internal/grpc/ByteStringUtilTest.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; +import org.assertj.core.api.Assertions; import org.junit.Test; import com.google.protobuf.ByteString; @@ -84,6 +85,14 @@ public void test_decodeIntValues() { assertArrayEquals(want, got); } + @Test + public void test_decodeNumberValues() { + byte[] bytes = { 0, 0, 0, 0, 0, 0, -16, 63, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 8, 64 }; + double[] want = { 1, 2, 3 }; + double[] got = ByteStringUtil.decodeNumberValues(ByteString.copyFrom(bytes)); + Assertions.assertThat(got).isEqualTo(want); + } + @Test(expected = IllegalArgumentException.class) public void test_decodeVector_1d_illegal() { byte[] bytes = new byte[Float.BYTES - 1]; // must be a multiple of Float.BYTES @@ -107,4 +116,10 @@ public void test_decodeIntValues_illegal() { byte[] bytes = new byte[Long.BYTES - 1]; // must be a multiple of Long.BYTES ByteStringUtil.decodeIntValues(ByteString.copyFrom(bytes)); } + + @Test(expected = IllegalArgumentException.class) + public void test_decodeNumberValues_illegal() { + byte[] bytes = new byte[Double.BYTES - 1]; // must be a multiple of Double.BYTES + ByteStringUtil.decodeNumberValues(ByteString.copyFrom(bytes)); + } } From 1af3fbbfdcd30e26d0deecdd673f669119f7d716 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 25 Aug 2025 18:34:08 +0200 Subject: [PATCH 15/17] refactor: put aggregation-factories behind Aggregate --- .../integration/AggregationITest.java | 10 +++--- .../api/collections/aggregate/Aggregate.java | 36 +++++++++++++++++++ .../collections/aggregate/Aggregation.java | 25 ------------- 3 files changed, 41 insertions(+), 30 deletions(-) create mode 100644 src/main/java/io/weaviate/client6/v1/api/collections/aggregate/Aggregate.java diff --git a/src/it/java/io/weaviate/integration/AggregationITest.java b/src/it/java/io/weaviate/integration/AggregationITest.java index 586cac1ea..e29da810f 100644 --- a/src/it/java/io/weaviate/integration/AggregationITest.java +++ b/src/it/java/io/weaviate/integration/AggregationITest.java @@ -16,9 +16,9 @@ import io.weaviate.client6.v1.api.collections.Property; import io.weaviate.client6.v1.api.collections.Vectorizers; import io.weaviate.client6.v1.api.collections.Vectors; +import io.weaviate.client6.v1.api.collections.aggregate.Aggregate; import io.weaviate.client6.v1.api.collections.aggregate.AggregateResponseGroup; import io.weaviate.client6.v1.api.collections.aggregate.AggregateResponseGrouped; -import io.weaviate.client6.v1.api.collections.aggregate.Aggregation; import io.weaviate.client6.v1.api.collections.aggregate.GroupBy; import io.weaviate.client6.v1.api.collections.aggregate.GroupedBy; import io.weaviate.client6.v1.api.collections.aggregate.IntegerAggregation; @@ -57,7 +57,7 @@ public void testOverAll() { var result = things.aggregate.overAll( with -> with .metrics( - Aggregation.integer("price", + Aggregate.integer("price", calculate -> calculate.median().max().count())) .includeTotalCount(true)); @@ -77,7 +77,7 @@ public void testOverAll_groupBy_category() { var result = things.aggregate.overAll( with -> with .metrics( - Aggregation.integer("price", + Aggregate.integer("price", calculate -> calculate.min().max().count())) .includeTotalCount(true), GroupBy.property("category")); @@ -115,7 +115,7 @@ public void testNearVector() { near -> near.limit(5), with -> with .metrics( - Aggregation.integer("price", + Aggregate.integer("price", calculate -> calculate.min().max().count())) .objectLimit(4) .includeTotalCount(true)); @@ -135,7 +135,7 @@ public void testNearVector_groupBy_category() { near -> near.distance(2f), with -> with .metrics( - Aggregation.integer("price", + Aggregate.integer("price", calculate -> calculate.min().max().median())) .objectLimit(9) .includeTotalCount(true), diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/Aggregate.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/Aggregate.java new file mode 100644 index 000000000..a8de946b5 --- /dev/null +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/Aggregate.java @@ -0,0 +1,36 @@ +package io.weaviate.client6.v1.api.collections.aggregate; + +import java.util.function.Function; + +import io.weaviate.client6.v1.internal.ObjectBuilder; + +public final class Aggregate { + /** Prevent public initialization. */ + private Aggregate() { + } + + public static final PropertyAggregation text(String property, + Function> fn) { + return TextAggregation.of(property, fn); + } + + public static final PropertyAggregation integer(String property, + Function> fn) { + return IntegerAggregation.of(property, fn); + } + + public static final PropertyAggregation bool(String property, + Function> fn) { + return BooleanAggregation.of(property, fn); + } + + public static final PropertyAggregation date(String property, + Function> fn) { + return DateAggregation.of(property, fn); + } + + public static final PropertyAggregation number(String property, + Function> fn) { + return NumberAggregation.of(property, fn); + } +} diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/Aggregation.java b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/Aggregation.java index 4dd8cb75f..26d8809f5 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/Aggregation.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/aggregate/Aggregation.java @@ -22,31 +22,6 @@ public static Aggregation of(AggregateObjectFilter objectFilter, Function> fn) { - return TextAggregation.of(property, fn); - } - - public static final PropertyAggregation integer(String property, - Function> fn) { - return IntegerAggregation.of(property, fn); - } - - public static final PropertyAggregation bool(String property, - Function> fn) { - return BooleanAggregation.of(property, fn); - } - - public static final PropertyAggregation date(String property, - Function> fn) { - return DateAggregation.of(property, fn); - } - - public static final PropertyAggregation number(String property, - Function> fn) { - return NumberAggregation.of(property, fn); - } - public Aggregation(Builder builder) { this( builder.objectFilter, From caff9905b4e3290c2c4ad396881ded72bc039e26 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 25 Aug 2025 18:35:31 +0200 Subject: [PATCH 16/17] feat: add more overload factories for Where Use primitive types where possible. Accept int where long is accepted. Accept float where double is accepted. List/Array properties only support Long/Double. --- .../v1/api/collections/query/Where.java | 112 ++++++++++++++---- 1 file changed, 86 insertions(+), 26 deletions(-) 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 7d0af64c0..bde53a695 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 @@ -123,7 +123,7 @@ public Where eq(String... values) { return new Where(Operator.EQUAL, left, new TextArrayOperand(values)); } - public Where eq(Boolean value) { + public Where eq(boolean value) { return new Where(Operator.EQUAL, left, new BooleanOperand(value)); } @@ -131,7 +131,11 @@ public Where eq(Boolean... values) { return new Where(Operator.EQUAL, left, new BooleanArrayOperand(values)); } - public Where eq(Long value) { + 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)); } @@ -139,7 +143,11 @@ public Where eq(Long... values) { return new Where(Operator.EQUAL, left, new IntegerArrayOperand(values)); } - public Where eq(Double value) { + 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)); } @@ -169,7 +177,7 @@ public Where ne(String... values) { return new Where(Operator.NOT_EQUAL, left, new TextArrayOperand(values)); } - public Where ne(Boolean value) { + public Where ne(boolean value) { return new Where(Operator.NOT_EQUAL, left, new BooleanOperand(value)); } @@ -177,7 +185,11 @@ public Where ne(Boolean... values) { return new Where(Operator.NOT_EQUAL, left, new BooleanArrayOperand(values)); } - public Where ne(Long value) { + 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)); } @@ -185,7 +197,11 @@ public Where ne(Long... values) { return new Where(Operator.NOT_EQUAL, left, new IntegerArrayOperand(values)); } - public Where ne(Double value) { + 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)); } @@ -215,7 +231,11 @@ public Where lt(String... values) { return new Where(Operator.LESS_THAN, left, new TextArrayOperand(values)); } - public Where lt(Long value) { + 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)); } @@ -223,7 +243,11 @@ public Where lt(Long... values) { return new Where(Operator.LESS_THAN, left, new IntegerArrayOperand(values)); } - public Where lt(Double value) { + 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)); } @@ -253,7 +277,11 @@ public Where lte(String... values) { return new Where(Operator.LESS_THAN_EQUAL, left, new TextArrayOperand(values)); } - public Where lte(Long value) { + 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)); } @@ -261,7 +289,11 @@ public Where lte(Long... values) { return new Where(Operator.LESS_THAN_EQUAL, left, new IntegerArrayOperand(values)); } - public Where lte(Double value) { + 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)); } @@ -291,7 +323,11 @@ public Where gt(String... values) { return new Where(Operator.GREATER_THAN, left, new TextArrayOperand(values)); } - public Where gt(Long value) { + 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)); } @@ -299,7 +335,11 @@ public Where gt(Long... values) { return new Where(Operator.GREATER_THAN, left, new IntegerArrayOperand(values)); } - public Where gt(Double value) { + 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)); } @@ -329,7 +369,11 @@ public Where gte(String... values) { return new Where(Operator.GREATER_THAN_EQUAL, left, new TextArrayOperand(values)); } - public Where gte(Long value) { + 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)); } @@ -337,7 +381,11 @@ public Where gte(Long... values) { return new Where(Operator.GREATER_THAN_EQUAL, left, new IntegerArrayOperand(values)); } - public Where gte(Double value) { + 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)); } @@ -454,10 +502,14 @@ static WhereOperand fromObject(Object value) { return new TextOperand(str); } else if (value instanceof Boolean bool) { return new BooleanOperand(bool); - } else if (value instanceof Long lng) { - return new IntegerOperand(lng); + } 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) { @@ -490,7 +542,7 @@ static WhereOperand fromObject(Object value) { } } throw new IllegalArgumentException( - "value must be either of String, Boolean, OffsetDateTime, Integer, Long, Double, Array/List of these types"); + "value must be either of String, Boolean, OffsetDateTime, Long, Double, or Array/List of these types"); } private static class PathOperand implements WhereOperand { @@ -561,9 +613,9 @@ public String toString() { } private static class BooleanOperand implements WhereOperand { - private final Boolean value; + private final boolean value; - private BooleanOperand(Boolean value) { + private BooleanOperand(boolean value) { this.value = value; } @@ -574,7 +626,7 @@ public void appendTo(WeaviateProtoBase.Filters.Builder where) { @Override public String toString() { - return value.toString(); + return Boolean.toString(value); } } @@ -602,9 +654,13 @@ public String toString() { } private static class IntegerOperand implements WhereOperand { - private final Long value; + private final long value; + + private IntegerOperand(long value) { + this.value = value; + } - private IntegerOperand(Long value) { + private IntegerOperand(int value) { this.value = value; } @@ -615,7 +671,7 @@ public void appendTo(WeaviateProtoBase.Filters.Builder where) { @Override public String toString() { - return value.toString(); + return Long.toString(value); } } @@ -643,9 +699,13 @@ public String toString() { } private static class NumberOperand implements WhereOperand { - private final Double value; + private final double value; - private NumberOperand(Double value) { + private NumberOperand(double value) { + this.value = value; + } + + private NumberOperand(float value) { this.value = value; } @@ -656,7 +716,7 @@ public void appendTo(WeaviateProtoBase.Filters.Builder where) { @Override public String toString() { - return value.toString(); + return Double.toString(value); } } From eef5bbce97951cd5de949674692e2619cbaeada9 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 25 Aug 2025 18:37:51 +0200 Subject: [PATCH 17/17] chore: fix javadoc --- src/main/java/io/weaviate/client6/v1/internal/DateUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/weaviate/client6/v1/internal/DateUtil.java b/src/main/java/io/weaviate/client6/v1/internal/DateUtil.java index dbd432481..b103e05e7 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/DateUtil.java +++ b/src/main/java/io/weaviate/client6/v1/internal/DateUtil.java @@ -15,7 +15,7 @@ public final class DateUtil { private DateUtil() { } - /** Convert ISO8601-formatted time string to {@Olink OffsetDateTime}. */ + /** Convert ISO8601-formatted time string to {@link OffsetDateTime}. */ public static OffsetDateTime fromISO8601(String iso8601) { return OffsetDateTime.parse(iso8601); }