Skip to content

Commit

Permalink
support * notation for all types of link traversals #323
Browse files Browse the repository at this point in the history
  • Loading branch information
aeberhart committed Jan 13, 2025
1 parent 613c533 commit 4ce3783
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 12 deletions.
58 changes: 52 additions & 6 deletions dashjoin-core/src/main/java/org/dashjoin/util/OpenCypher.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ static class Relation {
String name;
String variable;
Boolean left2right;
Integer from;
Integer to;
}

/**
Expand Down Expand Up @@ -81,7 +83,6 @@ Table parseTable(OpenCypherQuery.Table t) {
* query constructor - parsing is done in old code
*/
public OpenCypher(OpenCypherQuery query) {
System.out.println(query);
this.query = query;

patterns = new ArrayList<>();
Expand All @@ -103,6 +104,13 @@ public OpenCypher(OpenCypherQuery query) {
p.right = parseTable(i.table);
p.right.key = i.table.key;
p.right.value = i.table.value;
if (i.edge.star) {
p.relation.from = i.edge.from == null ? 1 : i.edge.from;
p.relation.to = i.edge.to == null ? 5 : i.edge.to;
} else {
p.relation.from = 1;
p.relation.to = 1;
}
left = p.right;
}
patterns.get(patterns.size() - 1).isLast = true;
Expand Down Expand Up @@ -149,20 +157,56 @@ class Path {
List<Binding> bindings;

boolean isSolution() {
Pattern last = bindings.get(bindings.size() - 1).pattern;
if (last.isLast)
if (last.relation != null)
if (numberOfMatches() < last.relation.from)
return false;
return bindings.get(bindings.size() - 1).pattern.isLast;
}

/**
* how often did the last pattern match
*/
int numberOfMatches() {

Pattern last = bindings.get(bindings.size() - 1).pattern;

int count = 0;
for (Binding b : bindings)
if (b.pattern == last)
count++;

return count;
}

/**
* given the current partial result, return the list of possible next patterns to traverse. This
* can be a list, because there are constructs like "traverse this link 1 or 2 times"
*/
List<Pattern> candidatePatterns() {
// TODO: only take next pattern for now
Pattern next = bindings.get(bindings.size() - 1).pattern.next;
if (next == null)
return Arrays.asList();
else

Pattern last = bindings.get(bindings.size() - 1).pattern;
Pattern next = last.next;

int count = 0;
for (Binding b : bindings)
if (b.pattern == last)
count++;

if (last.relation == null)
// we are at the start, return next if there is one
return Arrays.asList(next);

if (last.relation.from < count)
// we still need more edges with this relation
return Arrays.asList(last);

if (count < last.relation.to)
// we can either add another hop of the last relation or jump to the next
return Arrays.asList(last, next);

return Arrays.asList(next);
}

/**
Expand All @@ -187,6 +231,8 @@ void search(List<Map<String, Object>> res) throws Exception {
res.add(OpenCypher.this.query.project(r, path));
}
for (Pattern pattern : candidatePatterns()) {
if (pattern == null)
continue;
Binding b = bindings.get(bindings.size() - 1);

if (pattern.relation.left2right == null || pattern.relation.left2right) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ public static class Step {
public Map<String, Object> edge;
}

public boolean newEngine = false;
public boolean newEngine = true;

/**
* name of the path variable: MATCH path=(...
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import org.dashjoin.service.Services;
import org.dashjoin.util.OpenCypherQuery.Table;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentMatchers;
import org.mockito.Mockito;
Expand Down Expand Up @@ -283,18 +282,17 @@ public void testRange() throws Exception {
Assertions.assertEquals("[{from.ID=4, to.ID=1}]", res.toString());
}

@Disabled
@Test
public void testRange2() throws Exception {
List<Map<String, Object>> res =
run("MATCH (from:`dj/junit/NODE`)<-[*]-(to) RETURN from.ID, to.ID");
Assertions.assertEquals(4, res.size());

res = run("MATCH (from:`dj/junit/NODE` {ID:1})<-[*2..2]-(to) RETURN from.ID, to.ID");
Assertions.assertEquals("[{from.ID=4, to.ID=1}]", res.toString());
Assertions.assertEquals("[{from.ID=1, to.ID=4}]", res.toString());

res = run(
"MATCH (from:`dj/junit/NODE` {ID:4})<-[dj/junit/NODE/REL`*2..2]-(to) RETURN from.ID, to.ID");
Assertions.assertEquals("[{from.ID=4, to.ID=1}]", res.toString());
"MATCH (from:`dj/junit/NODE` {ID:1})<-[`dj/junit/NODE/REL`*2..2]-(to) RETURN from.ID, to.ID");
Assertions.assertEquals("[{from.ID=1, to.ID=4}]", res.toString());
}
}

0 comments on commit 4ce3783

Please sign in to comment.