diff --git a/src/main/java/technology/semi/weaviate/client/v1/graphql/query/argument/NearTextArgument.java b/src/main/java/technology/semi/weaviate/client/v1/graphql/query/argument/NearTextArgument.java index b6c540a8..9e6c6bf5 100644 --- a/src/main/java/technology/semi/weaviate/client/v1/graphql/query/argument/NearTextArgument.java +++ b/src/main/java/technology/semi/weaviate/client/v1/graphql/query/argument/NearTextArgument.java @@ -1,5 +1,6 @@ package technology.semi.weaviate.client.v1.graphql.query.argument; +import java.util.Arrays; import java.util.LinkedHashSet; import java.util.Set; import java.util.stream.Collectors; @@ -8,6 +9,7 @@ import lombok.Builder; import lombok.Getter; import lombok.experimental.FieldDefaults; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; @Getter @@ -22,21 +24,37 @@ public class NearTextArgument implements Argument { private String getConcepts(String[] concepts) { return Stream.of(concepts) - .map(f -> String.format("\"%s\"", f)) - .collect(Collectors.joining(", ")); + .map(f -> String.format("\"%s\"", f)) + .collect(Collectors.joining(", ")); } private String buildMoveParam(String name, NearTextMoveParameters moveParam) { Set arg = new LinkedHashSet<>(); - if (moveParam.getConcepts() != null && moveParam.getConcepts().length > 0) { + if (ArrayUtils.isNotEmpty(moveParam.getConcepts())) { arg.add(String.format("concepts: [%s]", getConcepts(moveParam.getConcepts()))); } if (moveParam.getForce() != null) { arg.add(String.format("force: %s", moveParam.getForce())); } + if (ArrayUtils.isNotEmpty(moveParam.getObjects())) { + String objects = Arrays.stream(moveParam.getObjects()) + .map(this::mapObjectMoveToStringClause).collect(Collectors.joining(",")); + arg.add(String.format("objects: [%s]", objects)); + } return String.format("%s: {%s}", name, StringUtils.joinWith(" ", arg.toArray())); } + private String mapObjectMoveToStringClause(NearTextMoveParameters.ObjectMove obj) { + Set objectsArg = new LinkedHashSet<>(); + if (StringUtils.isNotBlank(obj.getId())) { + objectsArg.add(String.format("id: \"%s\"", obj.getId())); + } + if (StringUtils.isNotBlank(obj.getBeacon())) { + objectsArg.add(String.format("beacon: \"%s\"", obj.getBeacon())); + } + return String.format("{%s}", StringUtils.joinWith(" ", objectsArg.toArray())); + } + @Override public String build() { Set arg = new LinkedHashSet<>(); diff --git a/src/main/java/technology/semi/weaviate/client/v1/graphql/query/argument/NearTextMoveParameters.java b/src/main/java/technology/semi/weaviate/client/v1/graphql/query/argument/NearTextMoveParameters.java index 5b276414..8c4e5440 100644 --- a/src/main/java/technology/semi/weaviate/client/v1/graphql/query/argument/NearTextMoveParameters.java +++ b/src/main/java/technology/semi/weaviate/client/v1/graphql/query/argument/NearTextMoveParameters.java @@ -2,6 +2,7 @@ import lombok.AccessLevel; import lombok.Builder; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.experimental.FieldDefaults; @@ -11,4 +12,14 @@ public class NearTextMoveParameters { String[] concepts; Float force; + ObjectMove[] objects; + + @Getter + @Builder + @FieldDefaults(level = AccessLevel.PRIVATE) + @EqualsAndHashCode + public static class ObjectMove { + String id; + String beacon; + } } diff --git a/src/test/java/technology/semi/weaviate/client/v1/graphql/query/argument/NearTextArgumentTest.java b/src/test/java/technology/semi/weaviate/client/v1/graphql/query/argument/NearTextArgumentTest.java index e1235a61..99c440a8 100644 --- a/src/test/java/technology/semi/weaviate/client/v1/graphql/query/argument/NearTextArgumentTest.java +++ b/src/test/java/technology/semi/weaviate/client/v1/graphql/query/argument/NearTextArgumentTest.java @@ -184,4 +184,134 @@ public void testBuildWithEmptyMoveToOrMoveAway() { Assert.assertEquals("nearText: {moveAwayFrom: {}}", arg2); Assert.assertEquals("nearText: {moveTo: {} moveAwayFrom: {}}", arg3); } + + @Test + public void testBuildMoveToWithObjects() { + // given + String[] concepts = new String[]{ "a", "b", "c" }; + NearTextMoveParameters moveTo1 = NearTextMoveParameters + .builder() + .objects(new NearTextMoveParameters.ObjectMove[]{ + NearTextMoveParameters.ObjectMove.builder().id("uuid").build(), + NearTextMoveParameters.ObjectMove.builder().beacon("beacon").build() + }) + .force(0.1f) + .build(); + NearTextMoveParameters moveTo2 = NearTextMoveParameters + .builder() + .objects(new NearTextMoveParameters.ObjectMove[]{ + NearTextMoveParameters.ObjectMove.builder().id("uuid").beacon("beacon").build(), + }) + .force(0.1f) + .build(); + NearTextMoveParameters moveTo3 = NearTextMoveParameters + .builder() + .objects(new NearTextMoveParameters.ObjectMove[]{ + NearTextMoveParameters.ObjectMove.builder().id("uuid").build(), + }) + .build(); + NearTextMoveParameters moveTo4 = NearTextMoveParameters + .builder() + .objects(new NearTextMoveParameters.ObjectMove[]{ + NearTextMoveParameters.ObjectMove.builder().beacon("beacon").build(), + }) + .build(); + NearTextArgument nearText1 = NearTextArgument.builder() + .concepts(concepts).certainty(0.8f).moveTo(moveTo1).build(); + NearTextArgument nearText2 = NearTextArgument.builder() + .concepts(concepts).certainty(0.8f).moveTo(moveTo2).build(); + NearTextArgument nearText3 = NearTextArgument.builder() + .concepts(concepts).certainty(0.8f).moveTo(moveTo3).build(); + NearTextArgument nearText4 = NearTextArgument.builder() + .concepts(concepts).certainty(0.8f).moveTo(moveTo4).build(); + // when + String arg1 = nearText1.build(); + String arg2 = nearText2.build(); + String arg3 = nearText3.build(); + String arg4 = nearText4.build(); + // then + Assert.assertEquals("nearText: {concepts: [\"a\", \"b\", \"c\"] certainty: 0.8 moveTo: {force: 0.1 objects: [{id: \"uuid\"},{beacon: \"beacon\"}]}}", arg1); + Assert.assertEquals("nearText: {concepts: [\"a\", \"b\", \"c\"] certainty: 0.8 moveTo: {force: 0.1 objects: [{id: \"uuid\" beacon: \"beacon\"}]}}", arg2); + Assert.assertEquals("nearText: {concepts: [\"a\", \"b\", \"c\"] certainty: 0.8 moveTo: {objects: [{id: \"uuid\"}]}}", arg3); + Assert.assertEquals("nearText: {concepts: [\"a\", \"b\", \"c\"] certainty: 0.8 moveTo: {objects: [{beacon: \"beacon\"}]}}", arg4); + } + + @Test + public void testBuildMoveAwayWithObjects() { + // given + String[] concepts = new String[]{ "a", "b", "c" }; + NearTextMoveParameters moveAwayFrom1 = NearTextMoveParameters + .builder() + .objects(new NearTextMoveParameters.ObjectMove[]{ + NearTextMoveParameters.ObjectMove.builder().id("uuid").build(), + NearTextMoveParameters.ObjectMove.builder().beacon("beacon").build() + }) + .force(0.1f) + .build(); + NearTextMoveParameters moveAwayFrom2 = NearTextMoveParameters + .builder() + .objects(new NearTextMoveParameters.ObjectMove[]{ + NearTextMoveParameters.ObjectMove.builder().id("uuid").beacon("beacon").build(), + }) + .force(0.1f) + .build(); + NearTextMoveParameters moveAwayFrom3 = NearTextMoveParameters + .builder() + .objects(new NearTextMoveParameters.ObjectMove[]{ + NearTextMoveParameters.ObjectMove.builder().id("uuid").build(), + }) + .build(); + NearTextMoveParameters moveAwayFrom4 = NearTextMoveParameters + .builder() + .objects(new NearTextMoveParameters.ObjectMove[]{ + NearTextMoveParameters.ObjectMove.builder().beacon("beacon").build(), + }) + .build(); + NearTextArgument nearText1 = NearTextArgument.builder() + .concepts(concepts).certainty(0.8f).moveAwayFrom(moveAwayFrom1).build(); + NearTextArgument nearText2 = NearTextArgument.builder() + .concepts(concepts).certainty(0.8f).moveAwayFrom(moveAwayFrom2).build(); + NearTextArgument nearText3 = NearTextArgument.builder() + .concepts(concepts).certainty(0.8f).moveAwayFrom(moveAwayFrom3).build(); + NearTextArgument nearText4 = NearTextArgument.builder() + .concepts(concepts).certainty(0.8f).moveAwayFrom(moveAwayFrom4).build(); + // when + String arg1 = nearText1.build(); + String arg2 = nearText2.build(); + String arg3 = nearText3.build(); + String arg4 = nearText4.build(); + // then + Assert.assertEquals("nearText: {concepts: [\"a\", \"b\", \"c\"] certainty: 0.8 moveAwayFrom: {force: 0.1 objects: [{id: \"uuid\"},{beacon: \"beacon\"}]}}", arg1); + Assert.assertEquals("nearText: {concepts: [\"a\", \"b\", \"c\"] certainty: 0.8 moveAwayFrom: {force: 0.1 objects: [{id: \"uuid\" beacon: \"beacon\"}]}}", arg2); + Assert.assertEquals("nearText: {concepts: [\"a\", \"b\", \"c\"] certainty: 0.8 moveAwayFrom: {objects: [{id: \"uuid\"}]}}", arg3); + Assert.assertEquals("nearText: {concepts: [\"a\", \"b\", \"c\"] certainty: 0.8 moveAwayFrom: {objects: [{beacon: \"beacon\"}]}}", arg4); + } + + @Test + public void testBuildMoveToAndMoveAwayFromWithObjects() { + // given + String[] concepts = new String[]{ "a", "b", "c" }; + NearTextMoveParameters moveTo = NearTextMoveParameters + .builder() + .objects(new NearTextMoveParameters.ObjectMove[]{ + NearTextMoveParameters.ObjectMove.builder().id("uuid").build(), + NearTextMoveParameters.ObjectMove.builder().beacon("beacon").build() + }) + .force(0.1f) + .build(); + NearTextMoveParameters moveAwayFrom = NearTextMoveParameters + .builder() + .objects(new NearTextMoveParameters.ObjectMove[]{ + NearTextMoveParameters.ObjectMove.builder().id("uuid").beacon("beacon").build(), + }) + .force(0.2f) + .build(); + NearTextArgument nearText1 = NearTextArgument.builder() + .concepts(concepts).certainty(0.8f).moveTo(moveTo).moveAwayFrom(moveAwayFrom).build(); + // when + String arg1 = nearText1.build(); + // then + Assert.assertEquals("nearText: {concepts: [\"a\", \"b\", \"c\"] certainty: 0.8 moveTo: {force: 0.1 objects: [{id: \"uuid\"},{beacon: \"beacon\"}]} " + + "moveAwayFrom: {force: 0.2 objects: [{id: \"uuid\" beacon: \"beacon\"}]}}", arg1); + } } diff --git a/src/test/java/technology/semi/weaviate/integration/client/graphql/ClientGraphQLTest.java b/src/test/java/technology/semi/weaviate/integration/client/graphql/ClientGraphQLTest.java index 669443a6..26a3a7cf 100644 --- a/src/test/java/technology/semi/weaviate/integration/client/graphql/ClientGraphQLTest.java +++ b/src/test/java/technology/semi/weaviate/integration/client/graphql/ClientGraphQLTest.java @@ -170,6 +170,70 @@ public void testGraphQLGetWithNearText() { assertEquals(1, getSoup.size()); } + @Test + public void testGraphQLGetWithNearTextAndMoveParams() { + // given + Config config = new Config("http", address); + WeaviateClient client = new WeaviateClient(config); + WeaviateTestGenerics testGenerics = new WeaviateTestGenerics(); + String newObjID1 = "6baed48e-2afe-4be4-a09d-b00a955d962b"; + String newObjID2 = "6baed48e-2afe-4be4-a09d-b00a955d962a"; + WeaviateObject pizzaWithID = WeaviateObject.builder().className("Pizza").id(newObjID1).properties(new HashMap() {{ + put("name", "JustPizza1"); + put("description", "Universally pizza with id"); + }}).build(); + WeaviateObject pizzaWithID2 = WeaviateObject.builder().className("Pizza").id(newObjID2).properties(new HashMap() {{ + put("name", "JustPizza2"); + put("description", "Universally pizza with some other id"); + }}).build(); + NearTextMoveParameters moveAway = NearTextMoveParameters.builder() + .objects(new NearTextMoveParameters.ObjectMove[]{ + NearTextMoveParameters.ObjectMove.builder().id(newObjID1).build() + }).force(0.9f).build(); + NearTextMoveParameters moveTo = NearTextMoveParameters.builder() + .objects(new NearTextMoveParameters.ObjectMove[]{ + NearTextMoveParameters.ObjectMove.builder().id(newObjID2).build() + }).force(0.9f).build(); + NearTextArgument nearText = client.graphQL().arguments().nearTextArgBuilder() + .concepts(new String[]{"Universally pizza with id"}) + .moveAwayFrom(moveAway) + .moveTo(moveTo) + .certainty(0.4f) + .build(); + Field name = Field.builder().name("name").build(); + Field _additional = Field.builder() + .name("_additional") + .fields(new Field[]{Field.builder().name("certainty").build()}) + .build(); + // when + testGenerics.createTestSchemaAndData(client); + Result insert = client.batch().objectsBatcher().withObject(pizzaWithID).withObject(pizzaWithID2).run(); + Result result = client.graphQL().get() + .withClassName("Pizza") + .withNearText(nearText) + .withFields(name, _additional) + .run(); + testGenerics.cleanupWeaviate(client); + // then + assertNotNull(insert); + assertNotNull(insert.getResult()); + assertEquals(2, insert.getResult().length); + assertNotNull(result); + assertFalse(result.hasErrors()); + GraphQLResponse resp = result.getResult(); + assertNotNull(resp); + assertNotNull(resp.getData()); + assertTrue(resp.getData() instanceof Map); + Map data = (Map) resp.getData(); + assertNotNull(data.get("Get")); + assertTrue(data.get("Get") instanceof Map); + Map get = (Map) data.get("Get"); + assertNotNull(get.get("Pizza")); + assertTrue(get.get("Pizza") instanceof List); + List pizzas = (List) get.get("Pizza"); + assertEquals(6, pizzas.size()); + } + @Test public void testGraphQLGetWithNearTextAndLimit() { // given diff --git a/src/test/java/technology/semi/weaviate/integration/client/misc/ClientMiscTest.java b/src/test/java/technology/semi/weaviate/integration/client/misc/ClientMiscTest.java index b17446ea..8f76ed2c 100644 --- a/src/test/java/technology/semi/weaviate/integration/client/misc/ClientMiscTest.java +++ b/src/test/java/technology/semi/weaviate/integration/client/misc/ClientMiscTest.java @@ -66,7 +66,7 @@ public void testMiscMetaEndpoint() { assertNotNull(meta); assertNull(meta.getError()); assertEquals("http://[::]:8080", meta.getResult().getHostname()); - assertEquals("1.13.1", meta.getResult().getVersion()); + assertEquals("1.13.2", meta.getResult().getVersion()); assertEquals("{text2vec-contextionary={version=en0.16.0-v1.0.2, wordCount=818072.0}}", meta.getResult().getModules().toString()); } } diff --git a/src/test/resources/docker-compose-test.yaml b/src/test/resources/docker-compose-test.yaml index 68d3f863..27b18581 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.13.1 + image: semitechnologies/weaviate:1.13.2 links: - "contextionary:contextionary" restart: on-failure:0