Skip to content

Commit cf871eb

Browse files
authored
Merge pull request #472 from weaviate/v6-orm-polish
v6: Handle missing properties in ORM scanning
2 parents 1e4a811 + fb03bd1 commit cf871eb

7 files changed

Lines changed: 76 additions & 11 deletions

File tree

‎README.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Weaviate Java client <img alt='Weaviate logo' src='https://github.com/weaviate/java-client/blob/v6/assets/duke-client6.png' width='200' align='right' />
1+
# Weaviate Java client <img alt='Weaviate logo' src='https://github.com/weaviate/java-client/blob/v6/logo.png' width='200' align='right' />
22

33
[![Build Status](https://github.com/weaviate/java-client/actions/workflows/.github/workflows/test.yaml/badge.svg?branch=main)](https://github.com/weaviate/java-client/actions/workflows/.github/workflows/test.yaml)
44

@@ -183,7 +183,7 @@ WeaviateClient wcd = WeaviateClient.connectToWeaviateCloud("my-cluster-url.io",
183183
> [!TIP]
184184
> The client holds a number of resources (HTTP connection pools, gRPC channel) which must be disposed of correclty then they are no longer needed.
185185
> If the client's lifecycle is tied to that of your app, closing the client via `client.close()` is a good way to do that.
186-
>
186+
>
187187
> Otherwise, use the client inside a [try-with-resources](https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html) statement:
188188
>
189189
>```java
@@ -684,7 +684,7 @@ var song1 = songs.query.byId(
684684
song -> song.returnReferences(QueryReference.single("artist"))
685685
);
686686
System.out.println(
687-
"Artist's last name is: " +
687+
"Artist's last name is: " +
688688
song1.properties().artist().lastName()
689689
);
690690
```
File renamed without changes.

‎src/it/java/io/weaviate/integration/ORMITest.java‎

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.weaviate.integration;
22

3+
import java.io.IOException;
34
import java.time.OffsetDateTime;
45
import java.util.List;
56
import java.util.Map;
@@ -14,6 +15,7 @@
1415
import io.weaviate.ConcurrentTest;
1516
import io.weaviate.client6.v1.api.WeaviateClient;
1617
import io.weaviate.client6.v1.api.collections.CollectionConfig;
18+
import io.weaviate.client6.v1.api.collections.WeaviateObject;
1719
import io.weaviate.client6.v1.api.collections.annotations.Collection;
1820
import io.weaviate.client6.v1.api.collections.annotations.Property;
1921
import io.weaviate.client6.v1.api.collections.data.InsertManyResponse.InsertObject;
@@ -23,7 +25,7 @@
2325
public class ORMITest extends ConcurrentTest {
2426
private static WeaviateClient client = Container.WEAVIATE.getClient();
2527

26-
@Collection("ORMITest")
28+
@Collection("ORMITestThings")
2729
static record Thing(
2830
// text / text[]
2931
String text,
@@ -95,7 +97,7 @@ public void test_createCollection() throws Exception {
9597

9698
// Assert
9799
Assertions.assertThat(config).get()
98-
.returns("ORMITest", CollectionConfig::collectionName)
100+
.returns("ORMITestThings", CollectionConfig::collectionName)
99101
.extracting(CollectionConfig::properties,
100102
InstanceOfAssertFactories.list(io.weaviate.client6.v1.api.collections.Property.class))
101103
.extracting(p -> Map.entry(
@@ -307,4 +309,45 @@ public void test_insertManyAndQuery() throws Exception {
307309
.usingRecursiveComparison(COMPARISON_CONFIG)
308310
.asInstanceOf(InstanceOfAssertFactories.list(Thing.class));
309311
}
312+
313+
@Collection("ORMITestSongs")
314+
record Song(
315+
String title,
316+
String album,
317+
int year,
318+
boolean hasAward,
319+
Long monthlyListeners) {
320+
}
321+
322+
/**
323+
* Test that serialization works correctly when some fields are null and
324+
* deserialization works correctly when some properties are not returned.
325+
*/
326+
@Test
327+
public void test_partialScan() throws IOException {
328+
client.collections.create(Song.class);
329+
330+
var songs = client.collections.use(Song.class);
331+
332+
// Act: insert with nulls
333+
var dystopia = songs.data.insert(new Song(
334+
"Dystopia",
335+
null,
336+
2016,
337+
true,
338+
null));
339+
340+
// Act: return subset of the properties
341+
var got = songs.query.byId(dystopia.uuid(),
342+
q -> q.returnProperties("title", "hasAward"));
343+
344+
// Assert
345+
Assertions.assertThat(got).get()
346+
.extracting(WeaviateObject::properties)
347+
.returns("Dystopia", Song::title)
348+
.returns(null, Song::album)
349+
.returns(0, Song::year)
350+
.returns(true, Song::hasAward)
351+
.returns(null, Song::monthlyListeners);
352+
}
310353
}

‎src/main/java/io/weaviate/client6/v1/api/collections/query/QueryRequest.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ private static <T> void setProperty(String property, WeaviateProtoProperties.Val
221221
} else if (value.hasBoolValue()) {
222222
builder.setBoolean(property, value.getBoolValue());
223223
} else if (value.hasIntValue()) {
224-
builder.setInteger(property, value.getIntValue());
224+
builder.setLong(property, value.getIntValue());
225225
} else if (value.hasNumberValue()) {
226226
builder.setDouble(property, value.getNumberValue());
227227
} else if (value.hasBlobValue()) {

‎src/main/java/io/weaviate/client6/v1/internal/orm/MapBuilder.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public void setBoolean(String property, Boolean value) {
2525
}
2626

2727
@Override
28-
public void setInteger(String property, Long value) {
28+
public void setLong(String property, Long value) {
2929
properties.put(property, value);
3030
}
3131

‎src/main/java/io/weaviate/client6/v1/internal/orm/PojoBuilder.java‎

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,34 @@
1111
import org.apache.commons.lang3.ArrayUtils;
1212

1313
final class PojoBuilder<PropertiesT extends Record> implements PropertiesBuilder<PropertiesT> {
14+
private static final Map<Class<?>, Object> PRIMITIVE_DEFAULTS;
15+
16+
static {
17+
PRIMITIVE_DEFAULTS = Map.of(
18+
boolean.class, false,
19+
short.class, (short) 0,
20+
int.class, 0,
21+
long.class, 0L,
22+
float.class, 0f,
23+
double.class, 0d);
24+
}
25+
1426
private final PojoDescriptor<PropertiesT> descriptor;
1527
private final Constructor<PropertiesT> ctor;
1628
private final Map<String, Arg> ctorArgs;
1729

1830
static record Arg(Class<?> type, Object value) {
31+
/**
32+
* Create a new Arg, replacing a null value with
33+
* default if the type is a known primitive class.
34+
*/
35+
static Arg withPrimitiveDefault(Class<?> type, Object value) {
36+
if (PRIMITIVE_DEFAULTS.containsKey(type)) {
37+
return new Arg(type, PRIMITIVE_DEFAULTS.get(type));
38+
}
39+
return new Arg(type, value);
40+
}
41+
1942
Arg withValue(Object value) {
2043
return new Arg(this.type, value);
2144
}
@@ -31,7 +54,7 @@ Arg withValue(Object value) {
3154
.map(arg -> {
3255
// LinkedHashMap allows null values.
3356
var type = arg.getType();
34-
ctorArgs.put(arg.getName(), new Arg(type, null));
57+
ctorArgs.put(arg.getName(), Arg.withPrimitiveDefault(type, null));
3558
return type;
3659
})
3760
.toArray(Class<?>[]::new);
@@ -103,8 +126,7 @@ public void setBoolean(String propertyName, Boolean value) {
103126
}
104127

105128
@Override
106-
// TODO: rename to setLong
107-
public void setInteger(String propertyName, Long value) {
129+
public void setLong(String propertyName, Long value) {
108130
if (isType(propertyName, short.class, Short.class)) {
109131
setValue(propertyName, value.shortValue());
110132
} else if (isType(propertyName, int.class, Integer.class)) {

‎src/main/java/io/weaviate/client6/v1/internal/orm/PropertiesBuilder.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public interface PropertiesBuilder<T> {
1111

1212
void setBoolean(String property, Boolean value);
1313

14-
void setInteger(String property, Long value);
14+
void setLong(String property, Long value);
1515

1616
void setDouble(String property, Double value);
1717

0 commit comments

Comments
 (0)