Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ Graph configuration properties are prefixed with `gremlin.arangodb.conf.graph`:
| `gremlin.arangodb.conf.graph.name` | ArangoDB graph name | `tinkerpop` |
| `gremlin.arangodb.conf.graph.enableDataDefinition` | Flag to allow data definition changes | `false` |
| `gremlin.arangodb.conf.graph.type` | Graph type: `SIMPLE` or `COMPLEX` | `SIMPLE` |
| `gremlin.arangodb.conf.graph.labelField` | Label field name | `_label` |
| `gremlin.arangodb.conf.graph.orphanCollections` | List of orphan collections names | - |
| `gremlin.arangodb.conf.graph.edgeDefinitions` | List of edge definitions | - |

Expand Down Expand Up @@ -395,6 +396,11 @@ The ArangoDB TinkerPop Provider supports two graph types, which can be configure
From an application perspective, this is the most flexible graph type that is backed by an ArangoDB graph composed of
only 1 vertex collection and 1 edge definition.

The `label` of each element is stored in a database document field. The label field name is configurable by setting the
configuration property `graph.labelField`, `_label` by default.

The `SIMPLE` graph type is the default graph type.

It has the following advantages:

- It closely matches the Tinkerpop property graph
Expand All @@ -407,7 +413,7 @@ It has the following disadvantages:
- All vertex types will be stored in the same vertex collection
- All edge types will be stored in the same edge collection
- It could not leverage the full potential of ArangoDB graph traversal
- It could require an index on the `_label` field to improve performance
- It could require an index on the label field to improve performance

Example configuration:

Expand Down Expand Up @@ -443,7 +449,11 @@ to `v/foo`).
### COMPLEX Graph Type

The `COMPLEX` graph type is backed by an ArangoDB graph composed potentially of multiple vertex collections and multiple
edge definitions. It has the following advantages:
edge definitions.

The `label` of each element is used as name for the related database collection.

It has the following advantages:

- It closely matches the ArangoDB graph structure
- It allows multiple vertex collections and multiple edge collections
Expand Down Expand Up @@ -502,10 +512,12 @@ collection, by default named `vertex`. In a `COMPLEX` graph, vertices are stored
Each vertex document contains:

- Standard ArangoDB fields (`_id`, `_key`, `_rev`)
- The field `_label`
- Vertex properties as document fields
- Meta-properties nested in the nested map `_meta`

Additionally, in a `SIMPLE` graph:
- The label field (`_label` by default)

For example, the following Java code:

[//]: <> (@formatter:off)
Expand Down Expand Up @@ -542,9 +554,11 @@ default named `edge`. In a `COMPLEX` graph, edges are stored in collections name
Each edge document contains:

- Standard ArangoDB edge fields (`_id`, `_key`, `_rev`, `_from`, `_to`)
- The field `_label`
- Edge properties as document fields

Additionally, in a `SIMPLE` graph:
- The label field (`_label` by default)

For example, the following Java code:

[//]: <> (@formatter:off)
Expand Down
5 changes: 5 additions & 0 deletions spotbugs/spotbugs-exclude.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,9 @@
<Bug pattern="SING_SINGLETON_HAS_NONPRIVATE_CONSTRUCTOR"/>
</Match>

<Match>
<Class name="com.arangodb.tinkerpop.gremlin.persistence.serde.SerdeModule"/>
<Bug pattern="SE_BAD_FIELD"/>
</Match>

</FindBugsFilter>
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public ArangoDBGraphClient(ArangoDBGraphConfig config, ElementIdFactory idFactor
.orElse(ArangoDefaults.DEFAULT_PROTOCOL);
ObjectMapper mapper = JacksonMapperProvider
.of(ContentTypeFactory.of(protocol))
.registerModule(new SerdeModule(idFactory, config.graphType));
.registerModule(new SerdeModule(idFactory, config));
aqlDeserializer = new AqlDeserializer(graph, mapper);
db = new ArangoDB.Builder()
.loadProperties(config.driverConfig)
Expand Down Expand Up @@ -305,7 +305,7 @@ public void updateVertex(ArangoDBVertex vertex) {

public Iterator<VertexData> getVertexNeighbors(ElementId vertexId, Set<String> edgeCollections, Direction direction, String[] labels) {
logger.debug("Get vertex {}:{} Neighbors, in {}, from collections {}", vertexId, direction, config.graphName, edgeCollections);
String query = ArangoDBQueryBuilder.readVertexNeighbors(config.graphName, direction, config.graphType, labels);
String query = ArangoDBQueryBuilder.readVertexNeighbors(config.graphName, direction, config, labels);
Map<String, Object> params = new HashMap<>();
params.put("vertexId", vertexId);
params.put("edgeCollections", edgeCollections);
Expand All @@ -317,7 +317,7 @@ public Iterator<VertexData> getVertexNeighbors(ElementId vertexId, Set<String> e

public Iterator<EdgeData> getVertexEdges(ElementId vertexId, Set<String> edgeCollections, Direction direction, String[] labels) {
logger.debug("Get vertex {}:{} Edges, in {}, from collections {}", vertexId, direction, config.graphName, edgeCollections);
String query = ArangoDBQueryBuilder.readVertexEdges(config.graphName, direction, config.graphType, labels);
String query = ArangoDBQueryBuilder.readVertexEdges(config.graphName, direction, config, labels);
Map<String, Object> params = new HashMap<>();
params.put("vertexId", vertexId);
params.put("edgeCollections", edgeCollections);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,36 +22,34 @@
import com.arangodb.tinkerpop.gremlin.structure.ArangoDBGraphConfig;
import org.apache.tinkerpop.gremlin.structure.Direction;

import static com.arangodb.tinkerpop.gremlin.utils.Fields.LABEL;


public class ArangoDBQueryBuilder {

private ArangoDBQueryBuilder() {
}

public static String readVertexNeighbors(String graphName, Direction direction, ArangoDBGraphConfig.GraphType type, String[] labels) {
return oneStepTraversal(graphName, direction, type, labels)
public static String readVertexNeighbors(String graphName, Direction direction, ArangoDBGraphConfig config, String[] labels) {
return oneStepTraversal(graphName, direction, config, labels)
.append(" RETURN v")
.toString();
}

public static String readVertexEdges(String graphName, Direction direction, ArangoDBGraphConfig.GraphType type, String[] labels) {
return oneStepTraversal(graphName, direction, type, labels)
public static String readVertexEdges(String graphName, Direction direction, ArangoDBGraphConfig config, String[] labels) {
return oneStepTraversal(graphName, direction, config, labels)
.append(" RETURN e")
.toString();
}

private static StringBuilder oneStepTraversal(String graphName, Direction direction, ArangoDBGraphConfig.GraphType type, String[] labels) {
private static StringBuilder oneStepTraversal(String graphName, Direction direction, ArangoDBGraphConfig config, String[] labels) {
StringBuilder query = new StringBuilder()
.append("FOR v, e IN 1..1 ")
.append(toArangoDirection(direction))
.append(" @vertexId GRAPH ")
.append(escape(graphName))
.append(" OPTIONS {edgeCollections: @edgeCollections}");
if (labels.length > 0) {
if (type == ArangoDBGraphConfig.GraphType.SIMPLE) {
query.append(" FILTER e." + LABEL + " IN @labels");
if (config.graphType == ArangoDBGraphConfig.GraphType.SIMPLE) {
query.append(" FILTER e." + config.labelField + " IN @labels");
} else {
query.append(" FILTER PARSE_COLLECTION(e) IN @edgeCollections");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import com.arangodb.tinkerpop.gremlin.persistence.EdgeData;
import com.arangodb.tinkerpop.gremlin.persistence.ElementId;
import com.arangodb.tinkerpop.gremlin.structure.ArangoDBGraphConfig;
import com.arangodb.tinkerpop.gremlin.utils.Fields;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
Expand All @@ -34,10 +33,10 @@

public class EdgeDataDeserializer extends JsonDeserializer<EdgeData> {

private final ArangoDBGraphConfig.GraphType type;
private final ArangoDBGraphConfig config;

public EdgeDataDeserializer(ArangoDBGraphConfig.GraphType type) {
this.type = type;
public EdgeDataDeserializer(ArangoDBGraphConfig config) {
this.config = config;
}

@Override
Expand All @@ -46,8 +45,8 @@ public EdgeData deserialize(JsonParser p, DeserializationContext ctx) throws IOE
ObjectNode root = c.readTree(p);
ElementId id = c.treeToValue(root.get(ID), ElementId.class);
String label;
if (type == ArangoDBGraphConfig.GraphType.SIMPLE) {
label = root.get(LABEL).asText();
if (config.graphType == ArangoDBGraphConfig.GraphType.SIMPLE) {
label = root.get(config.labelField).asText();
} else {
label = id.getLabel();
}
Expand All @@ -56,7 +55,7 @@ public EdgeData deserialize(JsonParser p, DeserializationContext ctx) throws IOE
EdgeData data = new EdgeData(label, id, from, to);

for (Map.Entry<String, JsonNode> prop : root.properties()) {
if (!Fields.isReserved(prop.getKey())) {
if (!config.isReservedField(prop.getKey())) {
data.put(prop.getKey(), c.treeToValue(prop.getValue(), Object.class));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@

public class EdgeDataSerializer extends JsonSerializer<EdgeData> {

private final ArangoDBGraphConfig.GraphType type;
private final ArangoDBGraphConfig config;

public EdgeDataSerializer(ArangoDBGraphConfig.GraphType type) {
this.type = type;
public EdgeDataSerializer(ArangoDBGraphConfig config) {
this.config = config;
}

@Override
Expand All @@ -42,8 +42,8 @@ public void serialize(EdgeData data, JsonGenerator gen, SerializerProvider seria
if (data.getKey() != null) {
gen.writeStringField(Fields.KEY, data.getKey());
}
if (type == ArangoDBGraphConfig.GraphType.SIMPLE) {
gen.writeStringField(LABEL, data.getLabel());
if (config.graphType == ArangoDBGraphConfig.GraphType.SIMPLE) {
gen.writeStringField(config.labelField, data.getLabel());
}
gen.writeObjectField(FROM, data.getFrom());
gen.writeObjectField(TO, data.getTo());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,27 @@

public class SerdeModule extends SimpleModule {
private final ElementIdFactory idFactory;
private final ArangoDBGraphConfig.GraphType graphType;
private final ArangoDBGraphConfig config;

public SerdeModule(ElementIdFactory idFactory, ArangoDBGraphConfig.GraphType graphType) {
public SerdeModule(ElementIdFactory idFactory, ArangoDBGraphConfig config) {
this.idFactory = idFactory;
this.graphType = graphType;
this.config = config;
}

@Override
public void setupModule(SetupContext context) {
SimpleSerializers serializers = new SimpleSerializers();
serializers.addSerializer(ElementId.class, new ElementIdSerializer());
serializers.addSerializer(VertexData.class, new VertexDataSerializer(graphType));
serializers.addSerializer(EdgeData.class, new EdgeDataSerializer(graphType));
serializers.addSerializer(VertexData.class, new VertexDataSerializer(config));
serializers.addSerializer(EdgeData.class, new EdgeDataSerializer(config));
serializers.addSerializer(VariablesData.class, new VariablesDataSerializer());
context.addSerializers(serializers);

SimpleDeserializers deserializers = new SimpleDeserializers();
deserializers.addDeserializer(ElementId.class, new ElementIdDeserializer(idFactory));
deserializers.addDeserializer(VertexData.class, new VertexDataDeserializer(graphType));
deserializers.addDeserializer(EdgeData.class, new EdgeDataDeserializer(graphType));
deserializers.addDeserializer(VariablesData.class, new VariablesDataDeserializer());
deserializers.addDeserializer(VertexData.class, new VertexDataDeserializer(config));
deserializers.addDeserializer(EdgeData.class, new EdgeDataDeserializer(config));
deserializers.addDeserializer(VariablesData.class, new VariablesDataDeserializer(config));
context.addDeserializers(deserializers);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package com.arangodb.tinkerpop.gremlin.persistence.serde;

import com.arangodb.tinkerpop.gremlin.persistence.VariablesData;
import com.arangodb.tinkerpop.gremlin.utils.Fields;
import com.arangodb.tinkerpop.gremlin.structure.ArangoDBGraphConfig;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
Expand All @@ -31,6 +31,12 @@
import static com.arangodb.tinkerpop.gremlin.utils.Fields.*;

public class VariablesDataDeserializer extends JsonDeserializer<VariablesData> {
private final ArangoDBGraphConfig config;

public VariablesDataDeserializer(ArangoDBGraphConfig config) {
this.config = config;
}

@Override
public VariablesData deserialize(JsonParser p, DeserializationContext ctx) throws IOException {
ObjectCodec c = p.getCodec();
Expand All @@ -40,7 +46,7 @@ public VariablesData deserialize(JsonParser p, DeserializationContext ctx) throw
VariablesData data = new VariablesData(key, version);

for (Map.Entry<String, JsonNode> prop : root.properties()) {
if (!Fields.isReserved(prop.getKey())) {
if (!config.isReservedField(prop.getKey())) {
data.put(prop.getKey(), c.treeToValue(prop.getValue(), Object.class));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import com.arangodb.tinkerpop.gremlin.persistence.VertexData;
import com.arangodb.tinkerpop.gremlin.persistence.VertexPropertyData;
import com.arangodb.tinkerpop.gremlin.structure.ArangoDBGraphConfig;
import com.arangodb.tinkerpop.gremlin.utils.Fields;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
Expand All @@ -36,10 +35,10 @@

class VertexDataDeserializer extends JsonDeserializer<VertexData> {

private final ArangoDBGraphConfig.GraphType type;
private final ArangoDBGraphConfig config;

VertexDataDeserializer(ArangoDBGraphConfig.GraphType type) {
this.type = type;
VertexDataDeserializer(ArangoDBGraphConfig config) {
this.config = config;
}

@Override
Expand All @@ -48,8 +47,8 @@ public VertexData deserialize(JsonParser p, DeserializationContext ctx) throws I
ObjectNode root = c.readTree(p);
ElementId id = c.treeToValue(root.get(ID), ElementId.class);
String label;
if (type == ArangoDBGraphConfig.GraphType.SIMPLE) {
label = root.get(LABEL).asText();
if (config.graphType == ArangoDBGraphConfig.GraphType.SIMPLE) {
label = root.get(config.labelField).asText();
} else {
label = id.getLabel();
}
Expand All @@ -60,7 +59,7 @@ public VertexData deserialize(JsonParser p, DeserializationContext ctx) throws I
: Collections.emptyMap();

for (Map.Entry<String, JsonNode> prop : root.properties()) {
if (!Fields.isReserved(prop.getKey())) {
if (!config.isReservedField(prop.getKey())) {
VertexPropertyData pd = new VertexPropertyData(c.treeToValue(prop.getValue(), Object.class));
String key = prop.getKey();
pd.putAll(meta.get(key));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,12 @@
import java.util.HashMap;
import java.util.Map;

import static com.arangodb.tinkerpop.gremlin.utils.Fields.LABEL;

class VertexDataSerializer extends JsonSerializer<VertexData> {

private final ArangoDBGraphConfig.GraphType type;
private final ArangoDBGraphConfig config;

VertexDataSerializer(ArangoDBGraphConfig.GraphType type) {
this.type = type;
VertexDataSerializer(ArangoDBGraphConfig config) {
this.config = config;
}

@Override
Expand All @@ -44,8 +42,8 @@ public void serialize(VertexData data, JsonGenerator gen, SerializerProvider ser
if (data.getKey() != null) {
gen.writeStringField(Fields.KEY, data.getKey());
}
if (type == ArangoDBGraphConfig.GraphType.SIMPLE) {
gen.writeStringField(LABEL, data.getLabel());
if (config.graphType == ArangoDBGraphConfig.GraphType.SIMPLE) {
gen.writeStringField(config.labelField, data.getLabel());
}

Map<String, Map<String, Object>> meta = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public class ArangoDBGraph implements Graph {

private final ArangoDBGraphClient client;
private final ElementIdFactory idFactory;
private final ArangoDBGraphConfig config;
public final ArangoDBGraphConfig config;

/**
* Open a new {@code ArangoDBGraph} instance.
Expand Down Expand Up @@ -280,7 +280,7 @@ public ArangoDBVertex createVertex(Object... keyValues) {
ElementId elementId = idFactory.createVertexId(label, id);
for (int i = 0; i < keyValues.length; i = i + 2) {
if (keyValues[i] instanceof String) {
ArangoDBUtil.validateProperty((String) keyValues[i], keyValues[i + 1]);
ArangoDBUtil.validateProperty((String) keyValues[i], keyValues[i + 1], config);
}
}
String inferredLabel = label != null ? label : Optional.ofNullable(elementId.getLabel()).orElse(Vertex.DEFAULT_LABEL);
Expand Down
Loading