Skip to content

Commit a97e1ad

Browse files
author
Mark
committed
replace graph_shortes_path function with aql
1 parent 2fd8547 commit a97e1ad

File tree

6 files changed

+194
-130
lines changed

6 files changed

+194
-130
lines changed

src/main/java/com/arangodb/ArangoDriver.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4397,7 +4397,7 @@ public <T> EdgeCursor<T> graphGetEdgeCursor(
43974397
validateCollectionName(graphName);
43984398

43994399
final MapBuilder mapBuilder = new MapBuilder();
4400-
final String query = GraphQueryUtil.createEdgeQuery(this, graphName, clazz, vertexExample, tmpGraphEdgesOptions,
4400+
final String query = GraphQueryUtil.createEdgeQuery(this, graphName, vertexExample, tmpGraphEdgesOptions,
44014401
mapBuilder);
44024402
final Map<String, Object> bindVars = mapBuilder.get();
44034403

@@ -4442,8 +4442,8 @@ public <T> VertexCursor<T> graphGetVertexCursor(
44424442
}
44434443

44444444
final MapBuilder mapBuilder = new MapBuilder();
4445-
final String query = GraphQueryUtil.createVerticesQuery(this, graphName, clazz, vertexExample,
4446-
tmpGraphVerticesOptions, mapBuilder);
4445+
final String query = GraphQueryUtil.createVerticesQuery(this, graphName, vertexExample, tmpGraphVerticesOptions,
4446+
mapBuilder);
44474447
final Map<String, Object> bindVars = mapBuilder.get();
44484448

44494449
return executeVertexQuery(query, bindVars, aqlQueryOptions, clazz);
@@ -4495,7 +4495,7 @@ public <V, E> ShortestPathEntity<V, E> graphGetShortestPath(
44954495
}
44964496

44974497
return cursorDriver.getShortestPath(getDefaultDatabase(), graphName, startVertexExample, endVertexExample,
4498-
tmpShortestPathOptions, getDefaultAqlQueryOptions(), vertexClass, edgeClass);
4498+
tmpShortestPathOptions, getDefaultAqlQueryOptions(), vertexClass, edgeClass, this);
44994499
}
45004500

45014501
/**

src/main/java/com/arangodb/InternalCursorDriver.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ public <V, E> ShortestPathEntity<V, E> getShortestPath(
9393
ShortestPathOptions shortestPathOptions,
9494
AqlQueryOptions aqlQueryOptions,
9595
Class<V> vertexClass,
96-
Class<E> edgeClass) throws ArangoException;
96+
Class<E> edgeClass,
97+
ArangoDriver driver) throws ArangoException;
9798

9899
QueryTrackingPropertiesEntity getQueryTrackingProperties(String database) throws ArangoException;
99100

src/main/java/com/arangodb/impl/InternalCursorDriverImpl.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.Map;
2121

2222
import com.arangodb.ArangoConfigure;
23+
import com.arangodb.ArangoDriver;
2324
import com.arangodb.ArangoException;
2425
import com.arangodb.CursorRawResult;
2526
import com.arangodb.CursorResult;
@@ -34,6 +35,7 @@
3435
import com.arangodb.http.HttpManager;
3536
import com.arangodb.http.HttpResponseEntity;
3637
import com.arangodb.util.AqlQueryOptions;
38+
import com.arangodb.util.GraphQueryUtil;
3739
import com.arangodb.util.MapBuilder;
3840
import com.arangodb.util.ShortestPathOptions;
3941
import com.google.gson.JsonObject;
@@ -171,19 +173,21 @@ public <V, E> ShortestPathEntity<V, E> getShortestPath(
171173
final ShortestPathOptions shortestPathOptions,
172174
final AqlQueryOptions aqlQueryOptions,
173175
final Class<V> vertexClass,
174-
final Class<E> edgeClass) throws ArangoException {
176+
final Class<E> edgeClass,
177+
final ArangoDriver driver) throws ArangoException {
175178

176179
validateCollectionName(graphName);
177180

178-
final String query = "for i in graph_shortest_path(@graphName, @startVertexExample, @endVertexExample, @options) return i";
179-
180-
final Map<String, Object> options = shortestPathOptions == null ? new MapBuilder().get()
181-
: shortestPathOptions.toMap();
181+
ShortestPathOptions tmpShortestPathOptions = shortestPathOptions;
182+
if (tmpShortestPathOptions == null) {
183+
tmpShortestPathOptions = new ShortestPathOptions();
184+
}
182185

183-
final Map<String, Object> bindVars = new MapBuilder().put("graphName", graphName)
184-
.put("startVertexExample", startVertexExample).put("endVertexExample", endVertexExample)
185-
.put("options", options).get();
186+
MapBuilder mapBuilder = new MapBuilder();
187+
final String query = GraphQueryUtil.createShortestPathQuery(driver, database, graphName, startVertexExample,
188+
endVertexExample, tmpShortestPathOptions, vertexClass, edgeClass, mapBuilder);
186189

190+
final Map<String, Object> bindVars = mapBuilder.get();
187191
final HttpResponseEntity res = getCursor(database, query, bindVars, aqlQueryOptions);
188192

189193
return createEntity(res, ShortestPathEntity.class, vertexClass, edgeClass);

src/main/java/com/arangodb/util/GraphEdgesOptions.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,9 @@ public Boolean getIncludeData() {
218218
*
219219
* @since ArangoDB 2.6
220220
*/
221-
public void setIncludeData(Boolean includeData) {
221+
public GraphEdgesOptions setIncludeData(Boolean includeData) {
222222
this.includeData = includeData;
223+
return this;
223224
}
224225

225226
}

src/main/java/com/arangodb/util/GraphQueryUtil.java

Lines changed: 158 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.arangodb.util;
22

3+
import java.util.ArrayList;
34
import java.util.List;
45
import java.util.Map.Entry;
56
import java.util.Set;
@@ -22,11 +23,14 @@ public class GraphQueryUtil {
2223
private static final String OR = " || ";
2324
private static final String GRAPH_NAME = "graphName";
2425
private static final String VERTEX_EXAMPLE = "vertexExample";
26+
private static final String START_VERTEX_EXAMPLE = "startVertexExample";
27+
private static final String END_VERTEX_EXAMPLE = "endVertexExample";
28+
private static final String SOURCE = "source";
29+
private static final String TARGET = "target";
2530

2631
public static String createEdgeQuery(
2732
final ArangoDriver driver,
2833
final String graphName,
29-
final Class<?> clazz,
3034
final Object vertexExample,
3135
final GraphEdgesOptions graphEdgesOptions,
3236
final MapBuilder bindVars) throws ArangoException {
@@ -36,50 +40,21 @@ public static String createEdgeQuery(
3640
sb.append("FOR v,e IN ");
3741
appendDepth(graphEdgesOptions, sb);
3842
appendDirection(graphEdgesOptions.getDirection(), sb);
39-
sb.append(" @");
40-
sb.append(VERTEX_EXAMPLE);
41-
bindVars.put(VERTEX_EXAMPLE, vertexExample);
43+
appendBindVar(VERTEX_EXAMPLE, vertexExample, bindVars, sb);
4244
} else {
4345
final List<String> startVertexCollectionRestriction = graphEdgesOptions
4446
.getStartVertexCollectionRestriction();
4547
final List<String> vertexCollections = startVertexCollectionRestriction != null
4648
&& startVertexCollectionRestriction.size() > 0 ? startVertexCollectionRestriction
4749
: driver.graphGetVertexCollections(graphName, true);
48-
if (vertexCollections.size() == 1) {
49-
sb.append("FOR start IN `");
50-
sb.append(vertexCollections.get(0));
51-
sb.append("`");
52-
appendFilter("start", vertexExample, sb);
53-
} else {
54-
sb.append("FOR start IN UNION (");
55-
for (String vertexCollection : vertexCollections) {
56-
sb.append("(FOR start IN `");
57-
sb.append(vertexCollection);
58-
sb.append("`");
59-
appendFilter("start", vertexExample, sb);
60-
sb.append(" RETURN start),");
61-
}
62-
// remove last ,
63-
sb.deleteCharAt(sb.length() - 1);
64-
sb.append(")");
65-
}
50+
appendFor("start", vertexExample, sb, vertexCollections);
6651
sb.append(" FOR v,e IN ");
6752
appendDepth(graphEdgesOptions, sb);
6853
appendDirection(graphEdgesOptions.getDirection(), sb);
6954
sb.append(" start");
7055
}
71-
sb.append(" ");
7256
final List<String> edgeCollectionRestriction = graphEdgesOptions.getEdgeCollectionRestriction();
73-
if (edgeCollectionRestriction != null && edgeCollectionRestriction.size() > 0) {
74-
for (String edgeCollection : edgeCollectionRestriction) {
75-
sb.append(edgeCollection);
76-
sb.append(",");
77-
}
78-
// remove last ,
79-
sb.deleteCharAt(sb.length() - 1);
80-
} else {
81-
appendGraphName(graphName, bindVars, sb);
82-
}
57+
appendEdgeCollectionsOrGraph(graphName, bindVars, sb, edgeCollectionRestriction);
8358
appendFilter("e", graphEdgesOptions.getEdgeExamples(), sb);
8459
appendFilter("v", graphEdgesOptions.getNeighborExamples(), sb);
8560
final Integer limit = graphEdgesOptions.getLimit();
@@ -96,15 +71,72 @@ public static String createEdgeQuery(
9671
return query;
9772
}
9873

99-
/**
100-
* @param graphName
101-
* @param bindVars
102-
* @param sb
103-
*/
74+
private static void appendEdgeCollectionsOrGraph(
75+
final String graphName,
76+
final MapBuilder bindVars,
77+
final StringBuilder sb,
78+
final List<String> edgeCollectionRestriction) {
79+
sb.append(" ");
80+
if (edgeCollectionRestriction != null && edgeCollectionRestriction.size() > 0) {
81+
for (String edgeCollection : edgeCollectionRestriction) {
82+
sb.append("`");
83+
sb.append(edgeCollection);
84+
sb.append("`,");
85+
}
86+
// remove last ,
87+
sb.deleteCharAt(sb.length() - 1);
88+
} else {
89+
appendGraphName(graphName, bindVars, sb);
90+
}
91+
}
92+
93+
private static void appendBindVar(
94+
final String param,
95+
final Object var,
96+
final MapBuilder bindVars,
97+
final StringBuilder sb) {
98+
sb.append(" @");
99+
sb.append(param);
100+
bindVars.put(param, var);
101+
}
102+
103+
private static void appendFor(
104+
final String var,
105+
final Object vertexExample,
106+
final StringBuilder sb,
107+
final List<String> vertexCollections) throws ArangoException {
108+
if (vertexCollections.size() == 1) {
109+
sb.append("FOR ");
110+
sb.append(var);
111+
sb.append(" IN `");
112+
sb.append(vertexCollections.get(0));
113+
sb.append("`");
114+
appendFilter(var, vertexExample, sb);
115+
} else {
116+
sb.append("FOR ");
117+
sb.append(var);
118+
sb.append(" IN UNION (");
119+
for (String vertexCollection : vertexCollections) {
120+
sb.append("(FOR ");
121+
sb.append(var);
122+
sb.append(" IN `");
123+
sb.append(vertexCollection);
124+
sb.append("`");
125+
appendFilter(var, vertexExample, sb);
126+
sb.append(" RETURN ");
127+
sb.append(var);
128+
sb.append("),");
129+
}
130+
// remove last ,
131+
sb.deleteCharAt(sb.length() - 1);
132+
sb.append(")");
133+
}
134+
sb.append(" ");
135+
}
136+
104137
private static void appendGraphName(final String graphName, final MapBuilder bindVars, final StringBuilder sb) {
105-
sb.append("GRAPH @");
106-
sb.append(GRAPH_NAME);
107-
bindVars.put(GRAPH_NAME, graphName);
138+
sb.append("GRAPH");
139+
appendBindVar(GRAPH_NAME, graphName, bindVars, sb);
108140
}
109141

110142
private static void appendDepth(final GraphEdgesOptions graphEdgesOptions, final StringBuilder sb) {
@@ -171,7 +203,6 @@ private static void appendObjectinFilter(final String var, final JsonObject json
171203
public static String createVerticesQuery(
172204
final ArangoDriver driver,
173205
final String graphName,
174-
final Class<?> clazz,
175206
final Object vertexExample,
176207
final GraphVerticesOptions graphVerticesOptions,
177208
final MapBuilder bindVars) throws ArangoException {
@@ -182,37 +213,18 @@ public static String createVerticesQuery(
182213
if (stringVertexExample) {
183214
sb.append("RETURN ");
184215
sb.append("DOCUMENT(");
185-
sb.append("@");
186-
sb.append(VERTEX_EXAMPLE);
187-
bindVars.put(VERTEX_EXAMPLE, vertexExample);
216+
appendBindVar(VERTEX_EXAMPLE, vertexExample, bindVars, sb);
188217
sb.append(")");
189218
} else {
190219
final List<String> startVertexCollectionRestriction = graphVerticesOptions.getVertexCollectionRestriction();
191220
final List<String> vertexCollections = startVertexCollectionRestriction != null
192221
&& startVertexCollectionRestriction.size() > 0 ? startVertexCollectionRestriction
193222
: driver.graphGetVertexCollections(graphName, true);
194-
if (vertexCollections.size() == 1) {
195-
sb.append("FOR start IN `");
196-
sb.append(vertexCollections.get(0));
197-
sb.append("`");
198-
appendFilter("start", vertexExample, sb);
199-
} else {
200-
sb.append("FOR start IN UNION (");
201-
for (String vertexCollection : vertexCollections) {
202-
sb.append("(FOR start IN `");
203-
sb.append(vertexCollection);
204-
sb.append("`");
205-
appendFilter("start", vertexExample, sb);
206-
sb.append(" RETURN start),");
207-
}
208-
// remove last ,
209-
sb.deleteCharAt(sb.length() - 1);
210-
sb.append(")");
211-
}
223+
appendFor("start", vertexExample, sb, vertexCollections);
212224
sb.append(" RETURN start");
213225
}
214226

215-
String query = sb.toString();
227+
final String query = sb.toString();
216228
return query;
217229
}
218230

@@ -225,7 +237,87 @@ public static String createShortestPathQuery(
225237
final ShortestPathOptions shortestPathOptions,
226238
final Class<?> vertexClass,
227239
final Class<?> edgeClass,
228-
final MapBuilder bindVars) {
229-
return null;
240+
final MapBuilder bindVars) throws ArangoException {
241+
/*
242+
*
243+
* final String query =
244+
* "for i in graph_shortest_path(@graphName, @startVertexExample, @endVertexExample, @options) return i"
245+
* ; final Map<String, Object> bindVars = mapBuilder.put("graphName",
246+
* graphName) .put("startVertexExample",
247+
* startVertexExample).put("endVertexExample", endVertexExample)
248+
* .put("options", options).get();
249+
*/
250+
final StringBuilder sb = new StringBuilder();
251+
final boolean notStringStartVertexExample = startVertexExample != null
252+
&& !String.class.isAssignableFrom(startVertexExample.getClass());
253+
boolean notStringEndVertexExample = endVertexExample != null
254+
&& !String.class.isAssignableFrom(endVertexExample.getClass());
255+
if (notStringStartVertexExample || notStringEndVertexExample) {
256+
final List<String> startVertexCollectionRestriction = shortestPathOptions
257+
.getStartVertexCollectionRestriction();
258+
final List<String> endVertexCollectionRestriction = shortestPathOptions.getEndVertexCollectionRestriction();
259+
final boolean startVertexCollectionRestrictionNotEmpty = startVertexCollectionRestriction != null
260+
&& startVertexCollectionRestriction.size() > 0;
261+
final boolean endVertexCollectionRestrictionNotEmpty = endVertexCollectionRestriction != null
262+
&& endVertexCollectionRestriction.size() > 0;
263+
final List<String> vertexCollections = (!startVertexCollectionRestrictionNotEmpty
264+
|| !endVertexCollectionRestrictionNotEmpty) ? driver.graphGetVertexCollections(graphName, true)
265+
: new ArrayList<String>();
266+
267+
if (notStringStartVertexExample) {
268+
final List<String> tmpStartVertexCollectionRestriction = startVertexCollectionRestrictionNotEmpty
269+
? startVertexCollectionRestriction : vertexCollections;
270+
appendFor(SOURCE, startVertexExample, sb, tmpStartVertexCollectionRestriction);
271+
}
272+
if (notStringEndVertexExample) {
273+
final List<String> tmpEndVertexCollectionRestriction = endVertexCollectionRestrictionNotEmpty
274+
? endVertexCollectionRestriction : vertexCollections;
275+
appendFor(TARGET, endVertexExample, sb, tmpEndVertexCollectionRestriction);
276+
}
277+
if (notStringStartVertexExample && notStringEndVertexExample) {
278+
sb.append("FILTER target != source ");
279+
}
280+
}
281+
{// p
282+
sb.append("LET p = ( FOR v, e IN ");
283+
appendDirection(shortestPathOptions.getDirection(), sb);
284+
sb.append(" SHORTEST_PATH ");
285+
if (notStringStartVertexExample) {
286+
sb.append(SOURCE);
287+
} else {
288+
appendBindVar(START_VERTEX_EXAMPLE, startVertexExample, bindVars, sb);
289+
}
290+
sb.append(" TO ");
291+
if (notStringEndVertexExample) {
292+
sb.append(TARGET);
293+
} else {
294+
appendBindVar(END_VERTEX_EXAMPLE, endVertexExample, bindVars, sb);
295+
}
296+
List<String> edgeCollectionRestriction = shortestPathOptions.getEdgeCollectionRestriction();
297+
appendEdgeCollectionsOrGraph(graphName, bindVars, sb, edgeCollectionRestriction);
298+
299+
final String weight = shortestPathOptions.getWeight();
300+
if (weight != null) {
301+
sb.append(" OPTIONS {weightAttribute: @attribute, defaultWeight: @default} ");
302+
sb.append(
303+
" RETURN { v: v, e: e, d: IS_NULL(e) ? 0 : (IS_NUMBER(e[@attribute]) ? e[@attribute] : @default))}) ");
304+
bindVars.put("attribute", weight);
305+
final Long defaultWeight = shortestPathOptions.getDefaultWeight();
306+
bindVars.put("default", defaultWeight != null ? defaultWeight : 1);
307+
} else {
308+
sb.append(" RETURN {v: v, e: e, d: IS_NULL(e) ? 0 : 1}) ");
309+
}
310+
}
311+
sb.append("FILTER LENGTH(p) > 0 ");
312+
if (shortestPathOptions.getIncludeData() != null && !shortestPathOptions.getIncludeData().booleanValue()) {
313+
sb.append(
314+
"RETURN { vertices: p[*].v._id, edges: p[* FILTER CURRENT.e != null].e._id, distance: SUM(p[*].d)}");
315+
} else {
316+
sb.append("RETURN { vertices: p[*].v, edges: p[* FILTER CURRENT.e != null].e, distance: SUM(p[*].d)}");
317+
}
318+
319+
final String query = sb.toString();
320+
System.out.println(query);
321+
return query;
230322
}
231323
}

0 commit comments

Comments
 (0)