diff --git a/src/main/java/io/weaviate/client/v1/schema/model/DataType.java b/src/main/java/io/weaviate/client/v1/schema/model/DataType.java
index 08625f5f..d8a7c6b2 100644
--- a/src/main/java/io/weaviate/client/v1/schema/model/DataType.java
+++ b/src/main/java/io/weaviate/client/v1/schema/model/DataType.java
@@ -16,6 +16,8 @@ public interface DataType {
String GEO_COORDINATES = "geoCoordinates";
String PHONE_NUMBER = "phoneNumber";
String UUID = "uuid";
+ String OBJECT = "object";
+
/**
* As of Weaviate v1.19 'string[]' is deprecated and replaced by 'text[]'.
* See data types
@@ -28,4 +30,5 @@ public interface DataType {
String BOOLEAN_ARRAY = "boolean[]";
String DATE_ARRAY = "date[]";
String UUID_ARRAY = "uuid[]";
+ String OBJECT_ARRAY = "object[]";
}
diff --git a/src/main/java/io/weaviate/client/v1/schema/model/Property.java b/src/main/java/io/weaviate/client/v1/schema/model/Property.java
index 409cc391..f287613b 100644
--- a/src/main/java/io/weaviate/client/v1/schema/model/Property.java
+++ b/src/main/java/io/weaviate/client/v1/schema/model/Property.java
@@ -28,4 +28,21 @@ public class Property {
Boolean indexFilterable;
Boolean indexSearchable;
Object moduleConfig;
+ List nestedProperties;
+
+
+ @Getter
+ @Builder
+ @ToString
+ @EqualsAndHashCode
+ @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
+ public static class NestedProperty {
+ String name;
+ List dataType;
+ String description;
+ String tokenization;
+ Boolean indexFilterable;
+ Boolean indexSearchable;
+ List nestedProperties;
+ }
}
diff --git a/src/test/java/io/weaviate/integration/client/WeaviateVersion.java b/src/test/java/io/weaviate/integration/client/WeaviateVersion.java
index ae679bf3..09ea62a5 100644
--- a/src/test/java/io/weaviate/integration/client/WeaviateVersion.java
+++ b/src/test/java/io/weaviate/integration/client/WeaviateVersion.java
@@ -3,9 +3,9 @@
public class WeaviateVersion {
// to be set according to weaviate docker image
- public static final String EXPECTED_WEAVIATE_VERSION = "1.21.0";
+ public static final String EXPECTED_WEAVIATE_VERSION = "1.21.5";
// to be set according to weaviate docker image
- public static final String EXPECTED_WEAVIATE_GIT_HASH = "8172acb";
+ public static final String EXPECTED_WEAVIATE_GIT_HASH = "8a40c6b";
private WeaviateVersion() {}
}
diff --git a/src/test/java/io/weaviate/integration/client/schema/ClientSchemaDefaultsAndMigrationTest.java b/src/test/java/io/weaviate/integration/client/schema/ClientSchemaDefaultsAndMigrationTest.java
index ea86d95a..cffe9d53 100644
--- a/src/test/java/io/weaviate/integration/client/schema/ClientSchemaDefaultsAndMigrationTest.java
+++ b/src/test/java/io/weaviate/integration/client/schema/ClientSchemaDefaultsAndMigrationTest.java
@@ -448,179 +448,179 @@ public static Object[][] provideInvalidForDataTypeAndIndexing() {
new Object[]{
DataType.TEXT,
Boolean.FALSE, null, Boolean.FALSE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.TEXT,
Boolean.FALSE, null, Boolean.TRUE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.TEXT,
Boolean.FALSE, Boolean.FALSE, null,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.TEXT,
Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.TEXT,
Boolean.FALSE, Boolean.FALSE, Boolean.TRUE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.TEXT,
Boolean.FALSE, Boolean.TRUE, null,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.TEXT,
Boolean.FALSE, Boolean.TRUE, Boolean.FALSE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.TEXT,
Boolean.FALSE, Boolean.TRUE, Boolean.TRUE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.TEXT,
Boolean.TRUE, null, Boolean.FALSE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.TEXT,
Boolean.TRUE, null, Boolean.TRUE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.TEXT,
Boolean.TRUE, Boolean.FALSE, null,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.TEXT,
Boolean.TRUE, Boolean.FALSE, Boolean.FALSE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.TEXT,
Boolean.TRUE, Boolean.FALSE, Boolean.TRUE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.TEXT,
Boolean.TRUE, Boolean.TRUE, null,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.TEXT,
Boolean.TRUE, Boolean.TRUE, Boolean.FALSE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.TEXT,
Boolean.TRUE, Boolean.TRUE, Boolean.TRUE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.INT,
Boolean.FALSE, null, Boolean.FALSE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.INT,
Boolean.FALSE, null, Boolean.TRUE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.INT,
Boolean.FALSE, Boolean.FALSE, null,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.INT,
Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.INT,
Boolean.FALSE, Boolean.FALSE, Boolean.TRUE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.INT,
Boolean.FALSE, Boolean.TRUE, null,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.INT,
Boolean.FALSE, Boolean.TRUE, Boolean.FALSE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.INT,
Boolean.FALSE, Boolean.TRUE, Boolean.TRUE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.INT,
Boolean.TRUE, null, Boolean.FALSE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.INT,
Boolean.TRUE, null, Boolean.TRUE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.INT,
Boolean.TRUE, Boolean.FALSE, null,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.INT,
Boolean.TRUE, Boolean.FALSE, Boolean.FALSE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.INT,
Boolean.TRUE, Boolean.FALSE, Boolean.TRUE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.INT,
Boolean.TRUE, Boolean.TRUE, null,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.INT,
Boolean.TRUE, Boolean.TRUE, Boolean.FALSE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.INT,
Boolean.TRUE, Boolean.TRUE, Boolean.TRUE,
- "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`.",
+ "`indexInverted` is deprecated and can not be set together with `indexFilterable` or `indexSearchable`",
},
new Object[]{
DataType.INT,
null, null, Boolean.TRUE,
- "`indexSearchable` is allowed only for text/text[] data types. For other data types set false or leave empty",
+ "`indexSearchable` is not allowed for other than text/text[] data types",
},
new Object[]{
DataType.INT,
null, Boolean.FALSE, Boolean.TRUE,
- "`indexSearchable` is allowed only for text/text[] data types. For other data types set false or leave empty",
+ "`indexSearchable` is not allowed for other than text/text[] data types",
},
new Object[]{
DataType.INT,
null, Boolean.TRUE, Boolean.TRUE,
- "`indexSearchable` is allowed only for text/text[] data types. For other data types set false or leave empty",
+ "`indexSearchable` is not allowed for other than text/text[] data types",
},
};
}
diff --git a/src/test/java/io/weaviate/integration/client/schema/ClientSchemaTest.java b/src/test/java/io/weaviate/integration/client/schema/ClientSchemaTest.java
index 6ddf3c27..67a12db2 100644
--- a/src/test/java/io/weaviate/integration/client/schema/ClientSchemaTest.java
+++ b/src/test/java/io/weaviate/integration/client/schema/ClientSchemaTest.java
@@ -4,6 +4,8 @@
import io.weaviate.client.WeaviateClient;
import io.weaviate.client.base.Result;
import io.weaviate.client.base.WeaviateErrorMessage;
+import io.weaviate.client.v1.batch.model.ObjectGetResponse;
+import io.weaviate.client.v1.data.model.WeaviateObject;
import io.weaviate.client.v1.misc.model.BM25Config;
import io.weaviate.client.v1.misc.model.DistanceType;
import io.weaviate.client.v1.misc.model.InvertedIndexConfig;
@@ -46,6 +48,7 @@
public class ClientSchemaTest {
private WeaviateClient client;
+ private final NestedObjectsUtils utils = new NestedObjectsUtils();
@ClassRule
public static DockerComposeContainer compose = new DockerComposeContainer(
@@ -995,4 +998,359 @@ private void assertPropertyEquals(String expectedName, String expectedDataType,
assertTrue(property.getDataType().size() > 0);
assertEquals(expectedDataType, property.getDataType().get(0));
}
+
+ @Test
+ public void shouldAddObjectsWithNestedProperties_EntireSchema() {
+ WeaviateClass schemaClass;
+ String className = "ClassWithObjectProperty";
+ Map expectedProps = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.INT);
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+
+ WeaviateClass wvtClass = utils.nestedClassEntireSchema(className);
+ utils.createClass(client, wvtClass);
+
+ schemaClass = utils.getClass(client, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedProps, schemaClass);
+
+ // schema did not change after adding object 1
+ WeaviateObject object1 = utils.createObject(client, utils.nestedObject1(className));
+ utils.assertThatObjectsAreSimilar(utils.expectedNestedObject1(className), object1);
+ schemaClass = utils.getClass(client, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedProps, schemaClass);
+
+ // schema did not change after adding object 2
+ WeaviateObject object2 = utils.createObject(client, utils.nestedObject2(className));
+ utils.assertThatObjectsAreSimilar(utils.expectedNestedObject2(className), object2);
+ schemaClass = utils.getClass(client, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedProps, schemaClass);
+ }
+
+ @Test
+ public void shouldAddObjectsWithNestedProperties_PartialSchema1() {
+ WeaviateClass schemaClass;
+ String className = "ClassWithObjectProperty";
+ Map expectedPropsStep1 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.INT);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+ Map expectedPropsStep2 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.INT);
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+
+ WeaviateClass wvtClass = utils.nestedClassPartialSchema1(className);
+ utils.createClass(client, wvtClass);
+
+ schemaClass = utils.getClass(client, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep1, schemaClass);
+
+ // schema did not change after adding object 1
+ WeaviateObject object1 = utils.createObject(client, utils.nestedObject1(className));
+ utils.assertThatObjectsAreSimilar(utils.expectedNestedObject1(className), object1);
+ schemaClass = utils.getClass(client, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep1, schemaClass);
+
+ // schema changed after adding object 2
+ WeaviateObject object2 = utils.createObject(client, utils.nestedObject2(className));
+ utils.assertThatObjectsAreSimilar(utils.expectedNestedObject2(className), object2);
+ schemaClass = utils.getClass(client, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep2, schemaClass);
+ }
+
+ @Test
+ public void shouldAddObjectsWithNestedProperties_PartialSchema2() {
+ WeaviateClass schemaClass;
+ String className = "ClassWithObjectProperty";
+ Map expectedPropsStep1 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+ Map expectedPropsStep2 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.NUMBER); // autoschema determines type as number
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+
+ WeaviateClass wvtClass = utils.nestedClassPartialSchema2(className);
+ utils.createClass(client, wvtClass);
+
+ schemaClass = utils.getClass(client, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep1, schemaClass);
+
+ // schema did not change after adding object 2
+ WeaviateObject object2 = utils.createObject(client, utils.nestedObject2(className));
+ utils.assertThatObjectsAreSimilar(utils.expectedNestedObject2(className), object2);
+ schemaClass = utils.getClass(client, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep1, schemaClass);
+
+ // schema changed after adding object 1
+ WeaviateObject object1 = utils.createObject(client, utils.nestedObject1(className));
+ utils.assertThatObjectsAreSimilar(utils.expectedNestedObject1(className), object1);
+ schemaClass = utils.getClass(client, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep2, schemaClass);
+ }
+
+ @Test
+ public void shouldAddObjectsWithNestedProperties_NoSchema1() {
+ WeaviateClass schemaClass;
+ String className = "ClassWithObjectProperty";
+ Map expectedPropsStep1 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.NUMBER); // autoschema determines type as number
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+ Map expectedPropsStep2 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.NUMBER);
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+
+ // schema created after adding object 1
+ WeaviateObject object1 = utils.createObject(client, utils.nestedObject1(className));
+ utils.assertThatObjectsAreSimilar(utils.expectedNestedObject1(className), object1);
+ schemaClass = utils.getClass(client, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep1, schemaClass);
+
+ // schema changed after adding object 2
+ WeaviateObject object2 = utils.createObject(client, utils.nestedObject2(className));
+ utils.assertThatObjectsAreSimilar(utils.expectedNestedObject2(className), object2);
+ schemaClass = utils.getClass(client, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep2, schemaClass);
+ }
+
+ @Test
+ public void shouldAddObjectsWithNestedProperties_NoSchema2() {
+ WeaviateClass schemaClass;
+ String className = "ClassWithObjectProperty";
+ Map expectedPropsStep1 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+ Map expectedPropsStep2 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.NUMBER); // autoschema determines type as number
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+
+ // schema created after adding object 2
+ WeaviateObject object2 = utils.createObject(client, utils.nestedObject2(className));
+ utils.assertThatObjectsAreSimilar(utils.expectedNestedObject2(className), object2);
+ schemaClass = utils.getClass(client, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep1, schemaClass);
+
+ // schema changed after adding object 1
+ WeaviateObject object1 = utils.createObject(client, utils.nestedObject1(className));
+ utils.assertThatObjectsAreSimilar(utils.expectedNestedObject1(className), object1);
+ schemaClass = utils.getClass(client, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep2, schemaClass);
+ }
+
+ @Test
+ public void shouldBatchObjectsWithNestedProperties_EntireSchema() {
+ WeaviateClass schemaClass;
+ String className = "ClassWithObjectProperty";
+ Map expectedProps = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.INT);
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+
+ WeaviateClass wvtClass = utils.nestedClassEntireSchema(className);
+ utils.createClass(client, wvtClass);
+
+ schemaClass = utils.getClass(client, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedProps, schemaClass);
+
+ // schema did not change after adding objects
+ ObjectGetResponse[] objects = utils.batchObjects(client, utils.nestedObject1(className), utils.nestedObject2(className));
+ utils.assertThatObjectsAreSimilar(utils.expectedNestedObject1(className), objects[0]);
+ utils.assertThatObjectsAreSimilar(utils.expectedNestedObject2(className), objects[1]);
+ schemaClass = utils.getClass(client, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedProps, schemaClass);
+ }
+
+ @Test
+ public void shouldBatchObjectsWithNestedProperties_PartialSchema1() {
+ WeaviateClass schemaClass;
+ String className = "ClassWithObjectProperty";
+ Map expectedPropsStep1 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.INT);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+ Map expectedPropsStep2 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.INT);
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+
+ WeaviateClass wvtClass = utils.nestedClassPartialSchema1(className);
+ utils.createClass(client, wvtClass);
+
+ schemaClass = utils.getClass(client, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep1, schemaClass);
+
+ // schema changed after adding objects
+ ObjectGetResponse[] objects = utils.batchObjects(client, utils.nestedObject1(className), utils.nestedObject2(className));
+ utils.assertThatObjectsAreSimilar(utils.expectedNestedObject1(className), objects[0]);
+ utils.assertThatObjectsAreSimilar(utils.expectedNestedObject2(className), objects[1]);
+ schemaClass = utils.getClass(client, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep2, schemaClass);
+ }
+
+ @Test
+ public void shouldBatchObjectsWithNestedProperties_PartialSchema2() {
+ WeaviateClass schemaClass;
+ String className = "ClassWithObjectProperty";
+ Map expectedPropsStep1 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+ Map expectedPropsStep2 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.NUMBER); // autoschema determines type as number
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+
+ WeaviateClass wvtClass = utils.nestedClassPartialSchema2(className);
+ utils.createClass(client, wvtClass);
+
+ schemaClass = utils.getClass(client, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep1, schemaClass);
+
+ // schema changed after adding objects
+ ObjectGetResponse[] objects = utils.batchObjects(client, utils.nestedObject1(className), utils.nestedObject2(className));
+ utils.assertThatObjectsAreSimilar(utils.expectedNestedObject1(className), objects[0]);
+ utils.assertThatObjectsAreSimilar(utils.expectedNestedObject2(className), objects[1]);
+ schemaClass = utils.getClass(client, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep2, schemaClass);
+ }
+
+ @Test
+ public void shouldBatchObjectsWithNestedProperties_NoSchema1() {
+ WeaviateClass schemaClass;
+ String className = "ClassWithObjectProperty";
+ Map expectedProps = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.NUMBER); // autoschema determines type as number
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+
+ // schema created after adding objects
+ ObjectGetResponse[] objects = utils.batchObjects(client, utils.nestedObject1(className), utils.nestedObject2(className));
+ utils.assertThatObjectsAreSimilar(utils.expectedNestedObject1(className), objects[0]);
+ utils.assertThatObjectsAreSimilar(utils.expectedNestedObject2(className), objects[1]);
+ schemaClass = utils.getClass(client, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedProps, schemaClass);
+ }
+
+ @Test
+ public void shouldBatchObjectsWithNestedProperties_NoSchema2() {
+ WeaviateClass schemaClass;
+ String className = "ClassWithObjectProperty";
+ Map expectedProps = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.NUMBER); // autoschema determines type as number
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+
+ // schema created after adding objects
+ ObjectGetResponse[] objects = utils.batchObjects(client, utils.nestedObject2(className), utils.nestedObject1(className));
+ utils.assertThatObjectsAreSimilar(utils.expectedNestedObject2(className), objects[0]);
+ utils.assertThatObjectsAreSimilar(utils.expectedNestedObject1(className), objects[1]);
+ schemaClass = utils.getClass(client, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedProps, schemaClass);
+ }
}
diff --git a/src/test/java/io/weaviate/integration/client/schema/ClusterSchemaTest.java b/src/test/java/io/weaviate/integration/client/schema/ClusterSchemaTest.java
index 1e69fdda..5e850f84 100644
--- a/src/test/java/io/weaviate/integration/client/schema/ClusterSchemaTest.java
+++ b/src/test/java/io/weaviate/integration/client/schema/ClusterSchemaTest.java
@@ -5,7 +5,10 @@
import io.weaviate.client.base.Result;
import io.weaviate.client.base.WeaviateError;
import io.weaviate.client.base.WeaviateErrorMessage;
+import io.weaviate.client.v1.batch.model.ObjectGetResponse;
+import io.weaviate.client.v1.data.model.WeaviateObject;
import io.weaviate.client.v1.misc.model.ReplicationConfig;
+import io.weaviate.client.v1.schema.model.DataType;
import io.weaviate.client.v1.schema.model.WeaviateClass;
import org.apache.http.HttpStatus;
import org.junit.After;
@@ -16,31 +19,41 @@
import org.testcontainers.containers.wait.strategy.Wait;
import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.InstanceOfAssertFactories.STRING;
public class ClusterSchemaTest {
- private WeaviateClient client;
+ private WeaviateClient client1;
+ private WeaviateClient client2;
+ private final NestedObjectsUtils utils = new NestedObjectsUtils();
@ClassRule
- public static DockerComposeContainer compose = new DockerComposeContainer(
+ public static DockerComposeContainer> compose = new DockerComposeContainer<>(
new File("src/test/resources/docker-compose-cluster.yaml")
- ).withExposedService("weaviate-node-1_1", 8087, Wait.forHttp("/v1/.well-known/ready").forStatusCode(200));
+ )
+ .withExposedService("weaviate-node-1_1", 8087, Wait.forHttp("/v1/.well-known/ready").forStatusCode(200))
+ .withExposedService("weaviate-node-2_1", 8088, Wait.forHttp("/v1/.well-known/ready").forStatusCode(200));
@Before
public void before() {
- String host = compose.getServiceHost("weaviate-node-1_1", 8087);
- Integer port = compose.getServicePort("weaviate-node-1_1", 8087);
- Config config = new Config("http", host + ":" + port);
+ String host1 = compose.getServiceHost("weaviate-node-1_1", 8087);
+ Integer port1 = compose.getServicePort("weaviate-node-1_1", 8087);
+ Config config1 = new Config("http", host1 + ":" + port1);
+ client1 = new WeaviateClient(config1);
- client = new WeaviateClient(config);
+ String host2 = compose.getServiceHost("weaviate-node-2_1", 8088);
+ Integer port2 = compose.getServicePort("weaviate-node-2_1", 8088);
+ Config config2 = new Config("http", host2 + ":" + port2);
+ client2 = new WeaviateClient(config2);
}
@After
public void after() {
- Result deleted = client.schema().allDeleter().run();
+ Result deleted = client1.schema().allDeleter().run();
assertThat(deleted.hasErrors()).isFalse();
}
@@ -58,13 +71,13 @@ public void shouldCreateClassWithImplicitReplicationFactor() {
.build();
// when
- Result createStatus = client.schema().classCreator().withClass(clazz).run();
+ Result createStatus = client1.schema().classCreator().withClass(clazz).run();
assertThat(createStatus).isNotNull()
.returns(false, Result::hasErrors)
.returns(true, Result::getResult);
// then
- Result classResult = client.schema().classGetter().withClassName(className).run();
+ Result classResult = client1.schema().classGetter().withClassName(className).run();
assertThat(classResult).isNotNull()
.returns(false, Result::hasErrors)
.extracting(Result::getResult).isNotNull()
@@ -89,13 +102,13 @@ public void shouldCreateClassWithExplicitReplicationFactor() {
.build();
// when
- Result createStatus = client.schema().classCreator().withClass(clazz).run();
+ Result createStatus = client1.schema().classCreator().withClass(clazz).run();
assertThat(createStatus).isNotNull()
.returns(false, Result::hasErrors)
.returns(true, Result::getResult);
// then
- Result classResult = client.schema().classGetter().withClassName(className).run();
+ Result classResult = client1.schema().classGetter().withClassName(className).run();
assertThat(classResult).isNotNull()
.returns(false, Result::hasErrors)
.extracting(Result::getResult).isNotNull()
@@ -120,7 +133,7 @@ public void shouldNotCreateClassWithTooHighFactor() {
.build();
// when
- Result createStatus = client.schema().classCreator().withClass(clazz).run();
+ Result createStatus = client1.schema().classCreator().withClass(clazz).run();
assertThat(createStatus).isNotNull()
.returns(true, Result::hasErrors)
.extracting(Result::getError)
@@ -129,5 +142,370 @@ public void shouldNotCreateClassWithTooHighFactor() {
.first()
.extracting(m -> ((WeaviateErrorMessage) m).getMessage()).asInstanceOf(STRING)
.contains("not enough replicas");
+ }@Test
+ public void shouldAddObjectsWithNestedProperties_EntireSchema() {
+ WeaviateClass schemaClass;
+ String className = "ClassWithObjectProperty";
+ Map expectedProps = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.INT);
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+
+ WeaviateClass wvtClass = utils.nestedClassEntireSchema(className);
+ utils.createClass(client1, wvtClass);
+
+ schemaClass = utils.getClass(client1, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedProps, schemaClass);
+ schemaClass = utils.getClass(client2, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedProps, schemaClass);
+
+ // schema did not change after adding object 1
+ utils.createObject(client1, utils.nestedObject1(className));
+ schemaClass = utils.getClass(client1, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedProps, schemaClass);
+ schemaClass = utils.getClass(client2, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedProps, schemaClass);
+
+ // schema did not change after adding object 2
+ utils.createObject(client1, utils.nestedObject2(className));
+ schemaClass = utils.getClass(client1, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedProps, schemaClass);
+ schemaClass = utils.getClass(client2, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedProps, schemaClass);
+ }
+
+ @Test
+ public void shouldAddObjectsWithNestedProperties_PartialSchema1() {
+ WeaviateClass schemaClass;
+ String className = "ClassWithObjectProperty";
+ Map expectedPropsStep1 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.INT);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+ Map expectedPropsStep2 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.INT);
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+
+ WeaviateClass wvtClass = utils.nestedClassPartialSchema1(className);
+ utils.createClass(client1, wvtClass);
+
+ schemaClass = utils.getClass(client1, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep1, schemaClass);
+
+ // schema did not change after adding object 1
+ utils.createObject(client1, utils.nestedObject1(className));
+ schemaClass = utils.getClass(client1, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep1, schemaClass);
+ schemaClass = utils.getClass(client2, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep1, schemaClass);
+
+ // schema changed after adding object 2
+ utils.createObject(client1, utils.nestedObject2(className));
+ schemaClass = utils.getClass(client1, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep2, schemaClass);
+ schemaClass = utils.getClass(client2, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep2, schemaClass);
+ }
+
+ @Test
+ public void shouldAddObjectsWithNestedProperties_PartialSchema2() {
+ WeaviateClass schemaClass;
+ String className = "ClassWithObjectProperty";
+ Map expectedPropsStep1 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+ Map expectedPropsStep2 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.NUMBER); // autoschema determines type as number
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+
+ WeaviateClass wvtClass = utils.nestedClassPartialSchema2(className);
+ utils.createClass(client1, wvtClass);
+
+ schemaClass = utils.getClass(client1, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep1, schemaClass);
+
+ // schema did not change after adding object 2
+ utils.createObject(client1, utils.nestedObject2(className));
+ schemaClass = utils.getClass(client1, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep1, schemaClass);
+ schemaClass = utils.getClass(client2, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep1, schemaClass);
+
+ // schema changed after adding object 1
+ utils.createObject(client1, utils.nestedObject1(className));
+ schemaClass = utils.getClass(client1, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep2, schemaClass);
+ schemaClass = utils.getClass(client2, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep2, schemaClass);
+ }
+
+ @Test
+ public void shouldAddObjectsWithNestedProperties_NoSchema1() {
+ WeaviateClass schemaClass;
+ String className = "ClassWithObjectProperty";
+ Map expectedPropsStep1 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.NUMBER); // autoschema determines type as number
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+ Map expectedPropsStep2 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.NUMBER);
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+
+ // schema created after adding object 1
+ utils.createObject(client1, utils.nestedObject1(className));
+ schemaClass = utils.getClass(client1, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep1, schemaClass);
+ schemaClass = utils.getClass(client2, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep1, schemaClass);
+
+ // schema changed after adding object 2
+ utils.createObject(client1, utils.nestedObject2(className));
+ schemaClass = utils.getClass(client1, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep2, schemaClass);
+ schemaClass = utils.getClass(client2, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep2, schemaClass);
+ }
+
+ @Test
+ public void shouldAddObjectsWithNestedProperties_NoSchema2() {
+ WeaviateClass schemaClass;
+ String className = "ClassWithObjectProperty";
+ Map expectedPropsStep1 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+ Map expectedPropsStep2 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.NUMBER); // autoschema determines type as number
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+
+ // schema created after adding object 2
+ utils.createObject(client1, utils.nestedObject2(className));
+ schemaClass = utils.getClass(client1, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep1, schemaClass);
+ schemaClass = utils.getClass(client2, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep1, schemaClass);
+
+ // schema changed after adding object 1
+ utils.createObject(client1, utils.nestedObject1(className));
+ schemaClass = utils.getClass(client1, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep2, schemaClass);
+ schemaClass = utils.getClass(client2, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep2, schemaClass);
+ }
+
+ @Test
+ public void shouldBatchObjectsWithNestedProperties_EntireSchema() {
+ WeaviateClass schemaClass;
+ String className = "ClassWithObjectProperty";
+ Map expectedProps = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.INT);
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+
+ WeaviateClass wvtClass = utils.nestedClassEntireSchema(className);
+ utils.createClass(client1, wvtClass);
+
+ schemaClass = utils.getClass(client1, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedProps, schemaClass);
+
+ // schema did not change after adding objects
+ utils.batchObjects(client1, utils.nestedObject1(className), utils.nestedObject2(className));
+ schemaClass = utils.getClass(client1, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedProps, schemaClass);
+ schemaClass = utils.getClass(client2, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedProps, schemaClass);
+ }
+
+ @Test
+ public void shouldBatchObjectsWithNestedProperties_PartialSchema1() {
+ WeaviateClass schemaClass;
+ String className = "ClassWithObjectProperty";
+ Map expectedPropsStep1 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.INT);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+ Map expectedPropsStep2 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.INT);
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+
+ WeaviateClass wvtClass = utils.nestedClassPartialSchema1(className);
+ utils.createClass(client1, wvtClass);
+
+ schemaClass = utils.getClass(client1, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep1, schemaClass);
+
+ // schema changed after adding objects
+ utils.batchObjects(client1, utils.nestedObject1(className), utils.nestedObject2(className));
+ schemaClass = utils.getClass(client1, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep2, schemaClass);
+ schemaClass = utils.getClass(client2, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep2, schemaClass);
+ }
+
+ @Test
+ public void shouldBatchObjectsWithNestedProperties_PartialSchema2() {
+ WeaviateClass schemaClass;
+ String className = "ClassWithObjectProperty";
+ Map expectedPropsStep1 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+ Map expectedPropsStep2 = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.NUMBER); // autoschema determines type as number
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+
+ WeaviateClass wvtClass = utils.nestedClassPartialSchema2(className);
+ utils.createClass(client1, wvtClass);
+
+ schemaClass = utils.getClass(client1, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep1, schemaClass);
+
+ // schema changed after adding objects
+ utils.batchObjects(client1, utils.nestedObject1(className), utils.nestedObject2(className));
+ schemaClass = utils.getClass(client1, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep2, schemaClass);
+ schemaClass = utils.getClass(client2, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedPropsStep2, schemaClass);
+ }
+
+ @Test
+ public void shouldBatchObjectsWithNestedProperties_NoSchema1() {
+ WeaviateClass schemaClass;
+ String className = "ClassWithObjectProperty";
+ Map expectedProps = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.NUMBER); // autoschema determines type as number
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+
+ // schema created after adding objects
+ utils.batchObjects(client1, utils.nestedObject1(className), utils.nestedObject2(className));
+ schemaClass = utils.getClass(client1, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedProps, schemaClass);
+ schemaClass = utils.getClass(client2, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedProps, schemaClass);
+ }
+
+ @Test
+ public void shouldBatchObjectsWithNestedProperties_NoSchema2() {
+ WeaviateClass schemaClass;
+ String className = "ClassWithObjectProperty";
+ Map expectedProps = new HashMap() {{
+ put("name", DataType.TEXT);
+ put("objectProperty", DataType.OBJECT);
+ put("objectProperty.nestedInt", DataType.NUMBER); // autoschema determines type as number
+ put("objectProperty.nestedNumber", DataType.NUMBER);
+ put("objectProperty.nestedText", DataType.TEXT);
+ put("objectProperty.nestedObjects", DataType.OBJECT_ARRAY);
+ put("objectProperty.nestedObjects.nestedBoolLvl2", DataType.BOOLEAN);
+ put("objectProperty.nestedObjects.nestedDateLvl2", DataType.DATE);
+ put("objectProperty.nestedObjects.nestedNumbersLvl2", DataType.NUMBER_ARRAY);
+ }};
+
+ // schema created after adding objects
+ utils.batchObjects(client1, utils.nestedObject2(className), utils.nestedObject1(className));
+ schemaClass = utils.getClass(client1, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedProps, schemaClass);
+ schemaClass = utils.getClass(client2, className);
+ utils.assertThatSchemaPropertiesHaveDataTypes(expectedProps, schemaClass);
}
}
diff --git a/src/test/java/io/weaviate/integration/client/schema/NestedObjectsUtils.java b/src/test/java/io/weaviate/integration/client/schema/NestedObjectsUtils.java
new file mode 100644
index 00000000..448c27c0
--- /dev/null
+++ b/src/test/java/io/weaviate/integration/client/schema/NestedObjectsUtils.java
@@ -0,0 +1,363 @@
+package io.weaviate.integration.client.schema;
+
+import io.weaviate.client.WeaviateClient;
+import io.weaviate.client.base.Result;
+import io.weaviate.client.v1.batch.model.ObjectGetResponse;
+import io.weaviate.client.v1.batch.model.ObjectGetResponseStatus;
+import io.weaviate.client.v1.batch.model.ObjectsGetResponseAO2Result;
+import io.weaviate.client.v1.data.model.WeaviateObject;
+import io.weaviate.client.v1.schema.model.DataType;
+import io.weaviate.client.v1.schema.model.Property;
+import io.weaviate.client.v1.schema.model.Schema;
+import io.weaviate.client.v1.schema.model.WeaviateClass;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.InstanceOfAssertFactories.ARRAY;
+
+class NestedObjectsUtils {
+
+ WeaviateClass nestedClassEntireSchema(String className) {
+ return WeaviateClass.builder()
+ .className(className)
+ .properties(Arrays.asList(
+ Property.builder()
+ .name("name")
+ .dataType(Arrays.asList(DataType.TEXT))
+ .build(),
+ Property.builder()
+ .name("objectProperty")
+ .dataType(Arrays.asList(DataType.OBJECT))
+ .nestedProperties(Arrays.asList(
+ Property.NestedProperty.builder()
+ .name("nestedInt")
+ .dataType(Arrays.asList(DataType.INT))
+ .build(),
+ Property.NestedProperty.builder()
+ .name("nestedNumber")
+ .dataType(Arrays.asList(DataType.NUMBER))
+ .build(),
+ Property.NestedProperty.builder()
+ .name("nestedText")
+ .dataType(Arrays.asList(DataType.TEXT))
+ .build(),
+ Property.NestedProperty.builder()
+ .name("nestedObjects")
+ .dataType(Arrays.asList(DataType.OBJECT_ARRAY))
+ .nestedProperties(Arrays.asList(
+ Property.NestedProperty.builder()
+ .name("nestedBoolLvl2")
+ .dataType(Arrays.asList(DataType.BOOLEAN))
+ .build(),
+ Property.NestedProperty.builder()
+ .name("nestedDateLvl2")
+ .dataType(Arrays.asList(DataType.DATE))
+ .build(),
+ Property.NestedProperty.builder()
+ .name("nestedNumbersLvl2")
+ .dataType(Arrays.asList(DataType.NUMBER_ARRAY))
+ .build()
+ ))
+ .build()
+ ))
+ .build()
+ ))
+ .build();
+ }
+
+ WeaviateClass nestedClassPartialSchema1(String className) {
+ return WeaviateClass.builder()
+ .className(className)
+ .properties(Arrays.asList(
+ Property.builder()
+ .name("name")
+ .dataType(Arrays.asList(DataType.TEXT))
+ .build(),
+ Property.builder()
+ .name("objectProperty")
+ .dataType(Arrays.asList(DataType.OBJECT))
+ .nestedProperties(Arrays.asList(
+ Property.NestedProperty.builder()
+ .name("nestedInt")
+ .dataType(Arrays.asList(DataType.INT))
+ .build(),
+ Property.NestedProperty.builder()
+ .name("nestedText")
+ .dataType(Arrays.asList(DataType.TEXT))
+ .build(),
+ Property.NestedProperty.builder()
+ .name("nestedObjects")
+ .dataType(Arrays.asList(DataType.OBJECT_ARRAY))
+ .nestedProperties(Arrays.asList(
+ Property.NestedProperty.builder()
+ .name("nestedBoolLvl2")
+ .dataType(Arrays.asList(DataType.BOOLEAN))
+ .build(),
+ Property.NestedProperty.builder()
+ .name("nestedNumbersLvl2")
+ .dataType(Arrays.asList(DataType.NUMBER_ARRAY))
+ .build()
+ ))
+ .build()
+ ))
+ .build()
+ ))
+ .build();
+ }
+
+ WeaviateClass nestedClassPartialSchema2(String className) {
+ return WeaviateClass.builder()
+ .className(className)
+ .properties(Arrays.asList(
+ Property.builder()
+ .name("name")
+ .dataType(Arrays.asList(DataType.TEXT))
+ .build(),
+ Property.builder()
+ .name("objectProperty")
+ .dataType(Arrays.asList(DataType.OBJECT))
+ .nestedProperties(Arrays.asList(
+ Property.NestedProperty.builder()
+ .name("nestedNumber")
+ .dataType(Arrays.asList(DataType.NUMBER))
+ .build(),
+ Property.NestedProperty.builder()
+ .name("nestedText")
+ .dataType(Arrays.asList(DataType.TEXT))
+ .build(),
+ Property.NestedProperty.builder()
+ .name("nestedObjects")
+ .dataType(Arrays.asList(DataType.OBJECT_ARRAY))
+ .nestedProperties(Arrays.asList(
+ Property.NestedProperty.builder()
+ .name("nestedDateLvl2")
+ .dataType(Arrays.asList(DataType.DATE))
+ .build(),
+ Property.NestedProperty.builder()
+ .name("nestedNumbersLvl2")
+ .dataType(Arrays.asList(DataType.NUMBER_ARRAY))
+ .build()
+ ))
+ .build()
+ ))
+ .build()
+ ))
+ .build();
+ }
+
+ WeaviateObject nestedObject1(String className) {
+ Map nestedPropsLvl2 = new HashMap<>();
+ nestedPropsLvl2.put("nestedBoolLvl2", false);
+ nestedPropsLvl2.put("nestedNumbersLvl2", Arrays.asList(1.1, 11.11));
+
+ Map nestedPropsLvl1 = new HashMap<>();
+ nestedPropsLvl1.put("nestedInt", 111);
+ nestedPropsLvl1.put("nestedText", "some text 1");
+ nestedPropsLvl1.put("nestedObjects", Arrays.asList(nestedPropsLvl2));
+
+ Map props = new HashMap<>();
+ props.put("name", "object1");
+ props.put("objectProperty", nestedPropsLvl1);
+
+ return WeaviateObject.builder()
+ .className(className)
+ .id("040f2b60-b1e8-4b4d-ba0d-14cedb5144ab")
+ .properties(props)
+ .build();
+ }
+
+ WeaviateObject expectedNestedObject1(String className) {
+ // overwrite ints with doubles, as they are unmarshalled as that type
+ WeaviateObject o = nestedObject1(className);
+ Map objectProperty = (Map) o.getProperties().get("objectProperty");
+ objectProperty.put("nestedInt", 111.0);
+
+ return o;
+ }
+
+ WeaviateObject nestedObject2(String className) {
+ Map nestedPropsLvl2 = new HashMap<>();
+ nestedPropsLvl2.put("nestedDateLvl2", "2022-01-01T00:00:00+02:00");
+ nestedPropsLvl2.put("nestedNumbersLvl2", Arrays.asList(2.2, 22.22));
+
+ Map nestedPropsLvl1 = new HashMap<>();
+ nestedPropsLvl1.put("nestedNumber", 222);
+ nestedPropsLvl1.put("nestedText", "some text 2");
+ nestedPropsLvl1.put("nestedObjects", Arrays.asList(nestedPropsLvl2));
+
+ Map props = new HashMap<>();
+ props.put("name", "object2");
+ props.put("objectProperty", nestedPropsLvl1);
+
+ return WeaviateObject.builder()
+ .className(className)
+ .id("d3ca0fc9-d392-4253-8f2a-0bce51efff80")
+ .properties(props)
+ .build();
+ }
+
+ WeaviateObject expectedNestedObject2(String className) {
+ // overwrite ints with doubles, as they are unmarshalled as that type
+ WeaviateObject o = nestedObject2(className);
+ Map objectProperty = (Map) o.getProperties().get("objectProperty");
+ objectProperty.put("nestedNumber", 222.0);
+
+ return o;
+ }
+
+ void createClass(WeaviateClient client, WeaviateClass wvtClass) {
+ Result createClass = client.schema().classCreator()
+ .withClass(wvtClass)
+ .run();
+
+ assertThat(createClass).isNotNull()
+ .returns(false, Result::hasErrors)
+ .returns(true, Result::getResult);
+ }
+
+ WeaviateClass getClass(WeaviateClient client, String className) {
+ Result getSchema = client.schema().getter().run();
+ assertThat(getSchema).isNotNull()
+ .returns(false, Result::hasErrors)
+ .extracting(Result::getResult).isNotNull();
+
+ Optional optionalClass = getSchema.getResult().getClasses().stream()
+ .filter(c -> className.equals(c.getClassName()))
+ .findFirst();
+ assertThat(optionalClass).isPresent();
+
+ return optionalClass.get();
+ }
+
+ WeaviateObject createObject(WeaviateClient client, WeaviateObject object) {
+ Result createObject = client.data().creator()
+ .withID(object.getId())
+ .withClassName(object.getClassName())
+ .withProperties(object.getProperties())
+ .run();
+
+ assertThat(createObject).isNotNull()
+ .returns(false, Result::hasErrors)
+ .extracting(Result::getResult).isNotNull();
+
+ return createObject.getResult();
+ }
+
+ ObjectGetResponse[] batchObjects(WeaviateClient client, WeaviateObject... objects) {
+ Result batchObjects = client.batch().objectsBatcher()
+ .withObjects(objects)
+ .run();
+
+ assertThat(batchObjects).isNotNull()
+ .returns(false, Result::hasErrors)
+ .extracting(Result::getResult).asInstanceOf(ARRAY)
+ .hasSize(objects.length);
+
+ Arrays.stream(batchObjects.getResult()).forEach(obj -> {
+ assertThat(obj).isNotNull()
+ .extracting(ObjectGetResponse::getResult).isNotNull()
+ .returns(ObjectGetResponseStatus.SUCCESS, ObjectsGetResponseAO2Result::getStatus)
+ .returns(null, ObjectsGetResponseAO2Result::getErrors);
+ });
+
+ return batchObjects.getResult();
+ }
+
+ void assertThatSchemaPropertiesHaveDataTypes(Map expectedProps, WeaviateClass schemaClass) {
+ Map>> propNumbers = expectedProps.entrySet().stream().collect(Collectors.groupingBy(entry -> {
+ String[] parts = StringUtils.split(entry.getKey(), ".");
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < parts.length - 1; i++) {
+ if (i != 0) {
+ sb.append(".");
+ }
+ sb.append(parts[i]);
+ }
+ return sb.toString();
+ }));
+
+ propNumbers.forEach((propName, props) -> {
+ if ("".equals(propName)) {
+ assertThat(schemaClass.getProperties()).isNotNull()
+ .hasSize(props.size());
+ } else {
+ String[] parts = StringUtils.split(propName, ".");
+ Optional optionalProp = schemaClass.getProperties().stream()
+ .filter(p -> parts[0].equals(p.getName()))
+ .findFirst();
+ assertThat(optionalProp).isPresent();
+
+ List nestedProps = optionalProp.get().getNestedProperties();
+
+ for (int i = 1; i < parts.length; i++) {
+ int index = i;
+ Optional optionalNestedProp = nestedProps.stream()
+ .filter(np -> parts[index].equals(np.getName()))
+ .findFirst();
+ assertThat(optionalNestedProp).isPresent();
+ nestedProps = optionalNestedProp.get().getNestedProperties();
+ }
+
+ assertThat(nestedProps).hasSize(props.size());
+ }
+ });
+
+ expectedProps.forEach((name, dataType) -> {
+ String[] parts = StringUtils.split(name, ".");
+ if (parts.length > 0) {
+ Optional optionalProp = schemaClass.getProperties().stream()
+ .filter(p -> parts[0].equals(p.getName()))
+ .findFirst();
+
+ assertThat(optionalProp).isPresent();
+ Property property = optionalProp.get();
+
+ if (parts.length == 1) {
+ assertThat(property)
+ .extracting(Property::getDataType).asList()
+ .first().isEqualTo(dataType);
+ } else {
+ Property.NestedProperty nestedProp = null;
+
+ List nestedProps = property.getNestedProperties();
+ for (int i = 1; i < parts.length; i++) {
+ int index = i;
+ assertThat(nestedProps).isNotNull();
+ Optional optionalNestedProp = nestedProps.stream()
+ .filter(np -> parts[index].equals(np.getName()))
+ .findFirst();
+ assertThat(optionalNestedProp).isPresent();
+ nestedProp = optionalNestedProp.get();
+ nestedProps = nestedProp.getNestedProperties();
+ }
+
+ assertThat(nestedProp).isNotNull()
+ .extracting(Property.NestedProperty::getDataType).asList()
+ .first().isEqualTo(dataType);
+ }
+ }
+ });
+ }
+
+ void assertThatObjectsAreSimilar(WeaviateObject expectedObject, WeaviateObject object) {
+ assertThat(object).isNotNull()
+ .returns(expectedObject.getId(), WeaviateObject::getId)
+ .returns(expectedObject.getClassName(), WeaviateObject::getClassName)
+ .extracting(WeaviateObject::getProperties)
+ .isEqualTo(expectedObject.getProperties());
+ }
+ void assertThatObjectsAreSimilar(WeaviateObject expectedObject, ObjectGetResponse object) {
+ assertThat(object).isNotNull()
+ .returns(expectedObject.getId(), ObjectGetResponse::getId)
+ .returns(expectedObject.getClassName(), ObjectGetResponse::getClassName)
+ .extracting(ObjectGetResponse::getProperties)
+ .isEqualTo(expectedObject.getProperties());
+ }
+}
diff --git a/src/test/resources/docker-compose-azure.yaml b/src/test/resources/docker-compose-azure.yaml
index 8820688c..9a9530a3 100644
--- a/src/test/resources/docker-compose-azure.yaml
+++ b/src/test/resources/docker-compose-azure.yaml
@@ -10,7 +10,7 @@ services:
- --scheme
- http
- --write-timeout=600s
- image: semitechnologies/weaviate:1.21.0
+ image: semitechnologies/weaviate:preview-adds-support-for-object-object-data-types-8a40c6b
restart: on-failure:0
environment:
PERSISTENCE_DATA_PATH: '/var/lib/weaviate'
diff --git a/src/test/resources/docker-compose-cluster.yaml b/src/test/resources/docker-compose-cluster.yaml
index 642765e0..f57fc8a1 100644
--- a/src/test/resources/docker-compose-cluster.yaml
+++ b/src/test/resources/docker-compose-cluster.yaml
@@ -10,7 +10,7 @@ services:
- --scheme
- http
- --write-timeout=600s
- image: semitechnologies/weaviate:1.21.0
+ image: semitechnologies/weaviate:preview-adds-support-for-object-object-data-types-8a40c6b
restart: on-failure:0
environment:
LOG_LEVEL: 'debug'
@@ -41,7 +41,7 @@ services:
- '8088'
- --scheme
- http
- image: semitechnologies/weaviate:1.21.0
+ image: semitechnologies/weaviate:preview-adds-support-for-object-object-data-types-8a40c6b
restart: on-failure:0
environment:
LOG_LEVEL: 'debug'
diff --git a/src/test/resources/docker-compose-okta-cc.yaml b/src/test/resources/docker-compose-okta-cc.yaml
index f81b4a21..e3bd1d2f 100644
--- a/src/test/resources/docker-compose-okta-cc.yaml
+++ b/src/test/resources/docker-compose-okta-cc.yaml
@@ -10,7 +10,7 @@ services:
- --scheme
- http
- --write-timeout=600s
- image: semitechnologies/weaviate:1.21.0
+ image: semitechnologies/weaviate:preview-adds-support-for-object-object-data-types-8a40c6b
restart: on-failure:0
environment:
PERSISTENCE_DATA_PATH: '/var/lib/weaviate'
diff --git a/src/test/resources/docker-compose-okta-users.yaml b/src/test/resources/docker-compose-okta-users.yaml
index b7304138..3a3f84d3 100644
--- a/src/test/resources/docker-compose-okta-users.yaml
+++ b/src/test/resources/docker-compose-okta-users.yaml
@@ -10,7 +10,7 @@ services:
- --scheme
- http
- --write-timeout=600s
- image: semitechnologies/weaviate:1.21.0
+ image: semitechnologies/weaviate:preview-adds-support-for-object-object-data-types-8a40c6b
restart: on-failure:0
environment:
PERSISTENCE_DATA_PATH: '/var/lib/weaviate'
diff --git a/src/test/resources/docker-compose-proxy.yaml b/src/test/resources/docker-compose-proxy.yaml
index cbe6dc62..35ca7171 100644
--- a/src/test/resources/docker-compose-proxy.yaml
+++ b/src/test/resources/docker-compose-proxy.yaml
@@ -9,7 +9,7 @@ services:
- '8080'
- --scheme
- http
- image: semitechnologies/weaviate:1.21.0
+ image: semitechnologies/weaviate:preview-adds-support-for-object-object-data-types-8a40c6b
restart: on-failure:0
environment:
LOG_LEVEL: "debug"
diff --git a/src/test/resources/docker-compose-test.yaml b/src/test/resources/docker-compose-test.yaml
index 8dec0f7d..e1dc288e 100644
--- a/src/test/resources/docker-compose-test.yaml
+++ b/src/test/resources/docker-compose-test.yaml
@@ -9,7 +9,7 @@ services:
- '8080'
- --scheme
- http
- image: semitechnologies/weaviate:1.21.0
+ image: semitechnologies/weaviate:preview-adds-support-for-object-object-data-types-8a40c6b
links:
- "contextionary:contextionary"
restart: on-failure:0
diff --git a/src/test/resources/docker-compose-wcs.yaml b/src/test/resources/docker-compose-wcs.yaml
index ffeb22dc..d05b8d07 100644
--- a/src/test/resources/docker-compose-wcs.yaml
+++ b/src/test/resources/docker-compose-wcs.yaml
@@ -10,7 +10,7 @@ services:
- --scheme
- http
- --write-timeout=600s
- image: semitechnologies/weaviate:1.21.0
+ image: semitechnologies/weaviate:preview-adds-support-for-object-object-data-types-8a40c6b
restart: on-failure:0
environment:
PERSISTENCE_DATA_PATH: '/var/lib/weaviate'