Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge from 0.2 #869

Merged
merged 16 commits into from
Jan 6, 2018
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
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package org.janusgraph.graphdb.tinkerpop.optimize;

import org.apache.tinkerpop.gremlin.process.traversal.P;
import org.apache.tinkerpop.gremlin.process.traversal.lambda.ElementValueTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.NoOpBarrierStep;
import org.apache.tinkerpop.gremlin.process.traversal.util.AndP;
Expand All @@ -32,7 +33,6 @@
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeGlobalStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderGlobalStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.IdentityStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.ElementValueComparator;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;

import org.javatuples.Pair;
Expand Down Expand Up @@ -76,17 +76,24 @@ static boolean validJanusGraphHas(Iterable<HasContainer> has) {

static boolean validJanusGraphOrder(OrderGlobalStep orderGlobalStep, Traversal rootTraversal,
boolean isVertexOrder) {
for (Pair<Traversal.Admin<Object, Comparable>, Comparator<Comparable>> comp : (List<Pair<Traversal.Admin<Object, Comparable>, Comparator<Comparable>>>) orderGlobalStep.getComparators()) {
if (!(comp.getValue1() instanceof ElementValueComparator)) return false;
ElementValueComparator evc = (ElementValueComparator) comp.getValue1();
if (!(evc.getValueComparator() instanceof Order)) return false;

JanusGraphTransaction tx = JanusGraphTraversalUtil.getTx(rootTraversal.asAdmin());
String key = evc.getPropertyKey();
PropertyKey propertyKey = tx.getPropertyKey(key);
if (propertyKey == null || !(Comparable.class.isAssignableFrom(propertyKey.dataType()))) return false;
if (isVertexOrder && propertyKey.cardinality() != Cardinality.SINGLE) return false;
final List<Pair<Traversal.Admin, Object>> comparators = orderGlobalStep.getComparators();
for(Pair<Traversal.Admin, Object> comp : comparators) {
if (comp.getValue0() instanceof ElementValueTraversal &&
comp.getValue1() instanceof Order) {
final String key = ((ElementValueTraversal) comp.getValue0()).getPropertyKey();
final JanusGraphTransaction tx = JanusGraphTraversalUtil.getTx(rootTraversal.asAdmin());
final PropertyKey pKey = tx.getPropertyKey(key);
if(pKey == null
|| !(Comparable.class.isAssignableFrom(pKey.dataType()))
|| (isVertexOrder && pKey.cardinality() != Cardinality.SINGLE)) {
return false;
}
} else {
// do not fold comparators that include nested traversals that are not simple ElementValues
return false;
}
}

return true;
}

Expand Down Expand Up @@ -118,10 +125,8 @@ static void foldInIds(final HasStepFolder janusgraphStep, final Traversal.Admin<
ids.addAll(Arrays.asList(graphStep.getIds()));
}
}
// clear ids to allow folding in ids from next HasContainer if relevant
graphStep.clearIds();
});
graphStep.addIds(ids);

if (!removableHasContainers.isEmpty()) {
removableHasContainers.forEach(hasContainerHolder::removeHasContainer);
}
Expand Down Expand Up @@ -178,9 +183,10 @@ static void foldInOrder(final HasStepFolder janusgraphStep, final Traversal.Admi
if (lastOrder != null) {
if (validJanusGraphOrder(lastOrder, rootTraversal, isVertexOrder)) {
//Add orders to HasStepFolder
for (Pair<Traversal.Admin<Object, Comparable>, Comparator<Comparable>> comp : (List<Pair<Traversal.Admin<Object, Comparable>, Comparator<Comparable>>>) ((OrderGlobalStep) lastOrder).getComparators()) {
ElementValueComparator evc = (ElementValueComparator) comp.getValue1();
janusgraphStep.orderBy(evc.getPropertyKey(), (Order) evc.getValueComparator());
for (Pair<Traversal.Admin<Object, Comparable>, Comparator<Object>> comp :
(List<Pair<Traversal.Admin<Object, Comparable>, Comparator<Object>>>) ((OrderGlobalStep) lastOrder).getComparators()) {
ElementValueTraversal evt = (ElementValueTraversal) comp.getValue0();
janusgraphStep.orderBy(evt.getPropertyKey(), (Order) comp.getValue1());
}
lastOrder.getLabels().forEach(janusgraphStep::addLabel);
traversal.removeStep(lastOrder);
Expand Down Expand Up @@ -208,6 +214,32 @@ public OrderEntry(String key, Order order) {
this.key = key;
this.order = order;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

OrderEntry that = (OrderEntry) o;

if (key != null ? !key.equals(that.key) : that.key != null) return false;
return order == that.order;
}

@Override
public int hashCode() {
int result = key != null ? key.hashCode() : 0;
result = 31 * result + (order != null ? order.hashCode() : 0);
return result;
}

@Override
public String toString() {
return "OrderEntry{" +
"key='" + key + '\'' +
", order=" + order +
'}';
}
}

static <E extends Ranging> void foldInRange(final HasStepFolder janusgraphStep, final Traversal.Admin<?, ?> traversal) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public JanusGraphStep(final GraphStep<S, E> originalStep) {
@Override
public String toString() {
return this.hasContainers.isEmpty() ?
super.toString() : StringFactory.stepString(this, Arrays.toString(this.ids), this.hasContainers);
super.toString() : StringFactory.stepString(this, Arrays.toString(this.ids), this.hasContainers, this.orders);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3508,9 +3508,16 @@ public void testTinkerPopOptimizationStrategies() {
assertNumStep(10, 1, gts.V(sv[0]).local(__.outE("knows").limit(10)), JanusGraphVertexStep.class);
assertNumStep(10, 1, gts.V(sv[0]).local(__.outE("knows").range(10, 20)), LocalStep.class);
assertNumStep(numV, 2, gts.V(sv[0]).outE("knows").order().by("weight", decr), JanusGraphVertexStep.class, OrderGlobalStep.class);
assertNumStep(10, 1, gts.V(sv[0]).local(__.outE("knows").order().by("weight", decr).limit(10)), LocalStep.class);
// Ensure the LocalStep is dropped because the Order can be folded in the JanusGraphVertexStep which in turn
// will allow JanusGraphLocalQueryOptimizationStrategy to drop the LocalStep as the local ordering will be
// provided by the single JanusGraphVertex step
assertNumStep(10, 0, gts.V(sv[0]).local(__.outE("knows").order().by("weight", decr).limit(10)), LocalStep.class);
assertNumStep(numV / 5, 2, gts.V(sv[0]).outE("knows").has("weight", 1).order().by("weight", incr), JanusGraphVertexStep.class, OrderGlobalStep.class);
assertNumStep(10, 1, gts.V(sv[0]).local(__.outE("knows").has("weight", 1).order().by("weight", incr).limit(10)), LocalStep.class);
assertNumStep(10, 0, gts.V(sv[0]).local(__.outE("knows").has("weight", 1).order().by("weight", incr).limit(10)), LocalStep.class);
// Note that for this test, the upper offset of the range will be folded into the JanusGraphVertexStep
// by JanusGraphLocalQueryOptimizationStrategy, but not the lower offset. The RangeGlobalStep will in turn be kept
// to enforce this lower bound and the LocalStep will be left as is as the local behavior will have not been
// entirely subsumed by the JanusGraphVertexStep
assertNumStep(5, 1, gts.V(sv[0]).local(__.outE("knows").has("weight", 1).has("weight", 1).order().by("weight", incr).range(10, 15)), LocalStep.class);
assertNumStep(1, 1, gts.V(sv[0]).outE("knows").filter(__.inV().is(vs[50])), JanusGraphVertexStep.class);
assertNumStep(1, 1, gts.V(sv[0]).outE("knows").filter(__.otherV().is(vs[50])), JanusGraphVertexStep.class);
Expand All @@ -3520,7 +3527,7 @@ public void testTinkerPopOptimizationStrategies() {
//Property
assertNumStep(numV / 5, 1, gts.V(sv[0]).properties("names").has("weight", 1), JanusGraphPropertiesStep.class);
assertNumStep(numV, 1, gts.V(sv[0]).properties("names"), JanusGraphPropertiesStep.class);
assertNumStep(10, 1, gts.V(sv[0]).local(__.properties("names").order().by("weight", decr).limit(10)), LocalStep.class);
assertNumStep(10, 0, gts.V(sv[0]).local(__.properties("names").order().by("weight", decr).limit(10)), LocalStep.class);
assertNumStep(numV, 2, gts.V(sv[0]).outE("knows").values("weight"), JanusGraphVertexStep.class, JanusGraphPropertiesStep.class);


Expand All @@ -3540,15 +3547,16 @@ public void testTinkerPopOptimizationStrategies() {
assertNumStep(superV * (numV / 5 * 2), 2, gts.V().has("id", sid).outE("knows").has("weight", P.gte(1)).has("weight", P.lt(3)), JanusGraphStep.class, JanusGraphVertexStep.class);
assertNumStep(superV * (numV / 5 * 2), 2, gts.V().has("id", sid).outE("knows").has("weight", P.between(1, 3)), JanusGraphStep.class, JanusGraphVertexStep.class);
assertNumStep(superV * 10, 2, gts.V().has("id", sid).local(__.outE("knows").has("weight", P.gte(1)).has("weight", P.lt(3)).limit(10)), JanusGraphStep.class, JanusGraphVertexStep.class);
assertNumStep(superV * 10, 2, gts.V().has("id", sid).local(__.outE("knows").has("weight", P.between(1, 3)).order().by("weight", decr).limit(10)), JanusGraphStep.class, LocalStep.class);

assertNumStep(superV * 10, 1, gts.V().has("id", sid).local(__.outE("knows").has("weight", P.between(1, 3)).order().by("weight", decr).limit(10)), JanusGraphStep.class);
assertNumStep(superV * 10, 0, gts.V().has("id", sid).local(__.outE("knows").has("weight", P.between(1, 3)).order().by("weight", decr).limit(10)), LocalStep.class);
clopen(option(USE_MULTIQUERY), true);
gts = graph.traversal();

assertNumStep(superV * (numV / 5), 2, gts.V().has("id", sid).outE("knows").has("weight", 1), JanusGraphStep.class, JanusGraphVertexStep.class);
assertNumStep(superV * (numV / 5 * 2), 2, gts.V().has("id", sid).outE("knows").has("weight", P.between(1, 3)), JanusGraphStep.class, JanusGraphVertexStep.class);
assertNumStep(superV * 10, 2, gts.V().has("id", sid).local(__.outE("knows").has("weight", P.gte(1)).has("weight", P.lt(3)).limit(10)), JanusGraphStep.class, JanusGraphVertexStep.class);
assertNumStep(superV * 10, 2, gts.V().has("id", sid).local(__.outE("knows").has("weight", P.between(1, 3)).order().by("weight", decr).limit(10)), JanusGraphStep.class, LocalStep.class);
assertNumStep(superV * 10, 1, gts.V().has("id", sid).local(__.outE("knows").has("weight", P.between(1, 3)).order().by("weight", decr).limit(10)), JanusGraphStep.class);
assertNumStep(superV * 10, 0, gts.V().has("id", sid).local(__.outE("knows").has("weight", P.between(1, 3)).order().by("weight", decr).limit(10)), LocalStep.class);
assertNumStep(superV * numV, 2, gts.V().has("id", sid).values("names"), JanusGraphStep.class, JanusGraphPropertiesStep.class);

//Verify traversal metrics when all reads are from cache (i.e. no backend queries)
Expand Down Expand Up @@ -3582,19 +3590,19 @@ private static void assertNumStep(int expectedResults, int expectedSteps, GraphT
traversal.next();
num++;
}
// System.out.println(traversal);

assertEquals(expectedResults, num);

//Verify that steps line up with what is expected after JanusGraph's optimizations are applied
List<Step> steps = traversal.asAdmin().getSteps();
Set<Class<? extends Step>> expSteps = Sets.newHashSet(expectedStepTypes);
int numSteps = 0;
for (Step s : steps) {
// System.out.println(s.getClass());
if (s.getClass().equals(GraphStep.class) || s.getClass().equals(StartStep.class)) continue;

assertTrue(s.getClass().getName(), expSteps.contains(s.getClass()));
numSteps++;
if (expSteps.contains(s.getClass())) {
numSteps++;
}
}
assertEquals(expectedSteps, numSteps);
}
Expand Down
Loading