Skip to content

Commit df8b0c7

Browse files
committed
feat: support batch inserting nested objects
1 parent 65b589f commit df8b0c7

2 files changed

Lines changed: 155 additions & 103 deletions

File tree

src/it/java/io/weaviate/integration/DataITest.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,32 @@ public void testDataTypes() throws IOException {
469469
}
470470

471471
@Test
472-
public void testNestedProperties() throws IOException {
472+
public void testNestedProperties_insertMany() throws IOException {
473+
// Arrange
474+
var nsBuildings = "Buildings";
475+
476+
client.collections.create(
477+
nsBuildings, c -> c.properties(
478+
Property.object("address", p -> p.nestedProperties(
479+
Property.text("street"),
480+
Property.integer("buildingNr"),
481+
Property.bool("isOneWay")))));
482+
483+
var buildings = client.collections.use("nsBuildings");
484+
485+
Map<String, Object> house_1 = Map.of("address", Map.of(
486+
"street", "Burggasse",
487+
"building_nr", 51,
488+
"isOneWay", true));
489+
Map<String, Object> house_2 = Map.of("address", Map.of(
490+
"street", "Port Mariland St.",
491+
"building_nr", 111,
492+
"isOneWay", false));
493+
494+
// Act
495+
var result = buildings.data.insertMany(house_1, house_2);
496+
497+
// Assert
498+
Assertions.assertThat(result.errors()).isEmpty();
473499
}
474500
}

src/main/java/io/weaviate/client6/v1/api/collections/data/InsertManyRequest.java

Lines changed: 128 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
import java.util.ArrayList;
55
import java.util.Arrays;
66
import java.util.List;
7+
import java.util.Map;
78
import java.util.UUID;
89

910
import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults;
1011
import io.weaviate.client6.v1.api.collections.ObjectMetadata;
1112
import io.weaviate.client6.v1.api.collections.WeaviateObject;
13+
import io.weaviate.client6.v1.internal.Debug;
1214
import io.weaviate.client6.v1.internal.MapUtil;
1315
import io.weaviate.client6.v1.internal.grpc.ByteStringUtil;
1416
import io.weaviate.client6.v1.internal.grpc.Rpc;
@@ -136,110 +138,15 @@ public static <T> void buildObject(WeaviateProtoBatch.BatchObject.Builder object
136138
collection
137139
.propertiesReader(insert.properties()).readProperties()
138140
.entrySet().stream().forEach(entry -> {
139-
var value = entry.getValue();
140-
var protoValue = com.google.protobuf.Value.newBuilder();
141-
142-
if (value == null) {
143-
return;
144-
}
145-
146-
if (value instanceof String v) {
147-
protoValue.setStringValue(v);
148-
} else if (value instanceof UUID v) {
149-
protoValue.setStringValue(v.toString());
150-
} else if (value instanceof OffsetDateTime v) {
151-
protoValue.setStringValue(v.toString());
152-
} else if (value instanceof Boolean v) {
153-
protoValue.setBoolValue(v.booleanValue());
154-
} else if (value instanceof Number v) {
155-
protoValue.setNumberValue(v.doubleValue());
156-
} else if (value instanceof List<?> v) {
157-
protoValue.setListValue(
158-
com.google.protobuf.ListValue.newBuilder()
159-
.addAllValues(v.stream()
160-
.map(listValue -> {
161-
var protoListValue = com.google.protobuf.Value.newBuilder();
162-
if (listValue instanceof String lv) {
163-
protoListValue.setStringValue(lv);
164-
} else if (listValue instanceof UUID lv) {
165-
protoListValue.setStringValue(lv.toString());
166-
} else if (listValue instanceof OffsetDateTime lv) {
167-
protoListValue.setStringValue(lv.toString());
168-
} else if (listValue instanceof Boolean lv) {
169-
protoListValue.setBoolValue(lv);
170-
} else if (listValue instanceof Number lv) {
171-
protoListValue.setNumberValue(lv.doubleValue());
172-
}
173-
return protoListValue.build();
174-
})
175-
.toList()));
176-
177-
} else if (value.getClass().isArray()) {
178-
List<com.google.protobuf.Value> values;
179-
180-
if (value instanceof String[] v) {
181-
values = Arrays.stream(v)
182-
.map(lv -> com.google.protobuf.Value.newBuilder().setStringValue(lv).build()).toList();
183-
} else if (value instanceof UUID[] v) {
184-
values = Arrays.stream(v)
185-
.map(lv -> com.google.protobuf.Value.newBuilder().setStringValue(lv.toString()).build()).toList();
186-
} else if (value instanceof OffsetDateTime[] v) {
187-
values = Arrays.stream(v)
188-
.map(lv -> com.google.protobuf.Value.newBuilder().setStringValue(lv.toString()).build()).toList();
189-
} else if (value instanceof Boolean[] v) {
190-
values = Arrays.stream(v)
191-
.map(lv -> com.google.protobuf.Value.newBuilder().setBoolValue(lv).build()).toList();
192-
} else if (value instanceof boolean[] v) {
193-
values = new ArrayList<>();
194-
for (boolean b : v) {
195-
values.add(com.google.protobuf.Value.newBuilder().setBoolValue(b).build());
196-
}
197-
} else if (value instanceof short[] v) {
198-
values = new ArrayList<>();
199-
for (short s : v) {
200-
values.add(com.google.protobuf.Value.newBuilder().setNumberValue(s).build());
201-
}
202-
} else if (value instanceof int[] v) {
203-
values = Arrays.stream(v).boxed()
204-
.map(lv -> com.google.protobuf.Value.newBuilder().setNumberValue(lv).build()).toList();
205-
} else if (value instanceof long[] v) {
206-
values = Arrays.stream(v).boxed()
207-
.map(lv -> com.google.protobuf.Value.newBuilder().setNumberValue(lv).build()).toList();
208-
} else if (value instanceof float[] v) {
209-
values = new ArrayList<>();
210-
for (float s : v) {
211-
values.add(com.google.protobuf.Value.newBuilder().setNumberValue(s).build());
212-
}
213-
} else if (value instanceof double[] v) {
214-
values = Arrays.stream(v).boxed()
215-
.map(lv -> com.google.protobuf.Value.newBuilder().setNumberValue(lv).build()).toList();
216-
} else if (value instanceof Short[] v) {
217-
values = Arrays.stream(v)
218-
.map(lv -> com.google.protobuf.Value.newBuilder().setNumberValue(lv).build()).toList();
219-
} else if (value instanceof Integer[] v) {
220-
values = Arrays.stream(v)
221-
.map(lv -> com.google.protobuf.Value.newBuilder().setNumberValue(lv).build()).toList();
222-
} else if (value instanceof Long[] v) {
223-
values = Arrays.stream(v)
224-
.map(lv -> com.google.protobuf.Value.newBuilder().setNumberValue(lv).build()).toList();
225-
} else if (value instanceof Float[] v) {
226-
values = Arrays.stream(v)
227-
.map(lv -> com.google.protobuf.Value.newBuilder().setNumberValue(lv).build()).toList();
228-
} else if (value instanceof Double[] v) {
229-
values = Arrays.stream(v)
230-
.map(lv -> com.google.protobuf.Value.newBuilder().setNumberValue(lv).build()).toList();
231-
} else {
232-
throw new AssertionError("(insertMany) branch not covered " + value.getClass());
141+
try {
142+
var protoValue = marshalValue(entry.getValue());
143+
if (protoValue == null) {
144+
return;
233145
}
234-
235-
protoValue.setListValue(com.google.protobuf.ListValue.newBuilder()
236-
.addAllValues(values)
237-
.build());
238-
} else {
239-
throw new AssertionError("(insertMany) branch not covered " + value.getClass());
146+
nonRef.putFields(entry.getKey(), protoValue);
147+
} catch (IllegalArgumentException e) {
148+
throw new IllegalArgumentException("marshal property " + entry.getKey(), e);
240149
}
241-
242-
nonRef.putFields(entry.getKey(), protoValue.build());
243150
});
244151

245152
insert.references()
@@ -272,5 +179,124 @@ public static <T> void buildObject(WeaviateProtoBatch.BatchObject.Builder object
272179
.addAllMultiTargetRefProps(multiRef);
273180

274181
object.setProperties(properties);
182+
183+
Debug.printProto(object);
184+
}
185+
186+
private static com.google.protobuf.Value marshalValue(Object value) {
187+
var protoValue = com.google.protobuf.Value.newBuilder();
188+
189+
if (value == null) {
190+
return null;
191+
}
192+
193+
if (value instanceof String v) {
194+
protoValue.setStringValue(v);
195+
} else if (value instanceof UUID v) {
196+
protoValue.setStringValue(v.toString());
197+
} else if (value instanceof OffsetDateTime v) {
198+
protoValue.setStringValue(v.toString());
199+
} else if (value instanceof Boolean v) {
200+
protoValue.setBoolValue(v.booleanValue());
201+
} else if (value instanceof Number v) {
202+
protoValue.setNumberValue(v.doubleValue());
203+
} else if (value instanceof List<?> v) {
204+
protoValue.setListValue(
205+
com.google.protobuf.ListValue.newBuilder()
206+
.addAllValues(v.stream()
207+
.map(listValue -> {
208+
var protoListValue = com.google.protobuf.Value.newBuilder();
209+
if (listValue instanceof String lv) {
210+
protoListValue.setStringValue(lv);
211+
} else if (listValue instanceof UUID lv) {
212+
protoListValue.setStringValue(lv.toString());
213+
} else if (listValue instanceof OffsetDateTime lv) {
214+
protoListValue.setStringValue(lv.toString());
215+
} else if (listValue instanceof Boolean lv) {
216+
protoListValue.setBoolValue(lv);
217+
} else if (listValue instanceof Number lv) {
218+
protoListValue.setNumberValue(lv.doubleValue());
219+
}
220+
return protoListValue.build();
221+
})
222+
.toList()));
223+
224+
} else if (value.getClass().isArray()) {
225+
List<com.google.protobuf.Value> values;
226+
227+
if (value instanceof String[] v) {
228+
values = Arrays.stream(v)
229+
.map(lv -> com.google.protobuf.Value.newBuilder().setStringValue(lv).build()).toList();
230+
} else if (value instanceof UUID[] v) {
231+
values = Arrays.stream(v)
232+
.map(lv -> com.google.protobuf.Value.newBuilder().setStringValue(lv.toString()).build()).toList();
233+
} else if (value instanceof OffsetDateTime[] v) {
234+
values = Arrays.stream(v)
235+
.map(lv -> com.google.protobuf.Value.newBuilder().setStringValue(lv.toString()).build()).toList();
236+
} else if (value instanceof Boolean[] v) {
237+
values = Arrays.stream(v)
238+
.map(lv -> com.google.protobuf.Value.newBuilder().setBoolValue(lv).build()).toList();
239+
} else if (value instanceof boolean[] v) {
240+
values = new ArrayList<>();
241+
for (boolean b : v) {
242+
values.add(com.google.protobuf.Value.newBuilder().setBoolValue(b).build());
243+
}
244+
} else if (value instanceof short[] v) {
245+
values = new ArrayList<>();
246+
for (short s : v) {
247+
values.add(com.google.protobuf.Value.newBuilder().setNumberValue(s).build());
248+
}
249+
} else if (value instanceof int[] v) {
250+
values = Arrays.stream(v).boxed()
251+
.map(lv -> com.google.protobuf.Value.newBuilder().setNumberValue(lv).build()).toList();
252+
} else if (value instanceof long[] v) {
253+
values = Arrays.stream(v).boxed()
254+
.map(lv -> com.google.protobuf.Value.newBuilder().setNumberValue(lv).build()).toList();
255+
} else if (value instanceof float[] v) {
256+
values = new ArrayList<>();
257+
for (float s : v) {
258+
values.add(com.google.protobuf.Value.newBuilder().setNumberValue(s).build());
259+
}
260+
} else if (value instanceof double[] v) {
261+
values = Arrays.stream(v).boxed()
262+
.map(lv -> com.google.protobuf.Value.newBuilder().setNumberValue(lv).build()).toList();
263+
} else if (value instanceof Short[] v) {
264+
values = Arrays.stream(v)
265+
.map(lv -> com.google.protobuf.Value.newBuilder().setNumberValue(lv).build()).toList();
266+
} else if (value instanceof Integer[] v) {
267+
values = Arrays.stream(v)
268+
.map(lv -> com.google.protobuf.Value.newBuilder().setNumberValue(lv).build()).toList();
269+
} else if (value instanceof Long[] v) {
270+
values = Arrays.stream(v)
271+
.map(lv -> com.google.protobuf.Value.newBuilder().setNumberValue(lv).build()).toList();
272+
} else if (value instanceof Float[] v) {
273+
values = Arrays.stream(v)
274+
.map(lv -> com.google.protobuf.Value.newBuilder().setNumberValue(lv).build()).toList();
275+
} else if (value instanceof Double[] v) {
276+
values = Arrays.stream(v)
277+
.map(lv -> com.google.protobuf.Value.newBuilder().setNumberValue(lv).build()).toList();
278+
} else {
279+
throw new IllegalArgumentException("array type " + value.getClass() + " is not supported");
280+
}
281+
282+
protoValue.setListValue(com.google.protobuf.ListValue.newBuilder()
283+
.addAllValues(values)
284+
.build());
285+
} else if (value instanceof Map<?, ?> v) {
286+
var protoNested = com.google.protobuf.Struct.newBuilder();
287+
v.entrySet().stream()
288+
.forEach(nested -> {
289+
var nestedValue = marshalValue(nested.getValue());
290+
if (nestedValue == null) {
291+
return;
292+
}
293+
protoNested.putFields((String) nested.getKey(), nestedValue);
294+
});
295+
protoValue.setStructValue(protoNested);
296+
} else {
297+
throw new IllegalArgumentException("data type " + value.getClass() + " is not supported");
298+
}
299+
300+
return protoValue.build();
275301
}
276302
}

0 commit comments

Comments
 (0)