perf(core): add AdjacentEdgesQuery
Change-Id: Ie7169fdb707495ff0a298ea97fa4d105117a132d
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/AdjacentEdgesQuery.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/AdjacentEdgesQuery.java
new file mode 100644
index 0000000..b1d3c1e
--- /dev/null
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/AdjacentEdgesQuery.java
@@ -0,0 +1,396 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hugegraph.backend.query;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.hugegraph.backend.id.Id;
+import org.apache.hugegraph.backend.query.Condition.Relation;
+import org.apache.hugegraph.backend.query.Condition.RelationType;
+import org.apache.hugegraph.structure.HugeEdge;
+import org.apache.hugegraph.structure.HugeElement;
+import org.apache.hugegraph.type.HugeType;
+import org.apache.hugegraph.type.define.Directions;
+import org.apache.hugegraph.type.define.HugeKeys;
+import org.apache.hugegraph.util.CollectionUtil;
+import org.apache.hugegraph.util.E;
+import org.apache.hugegraph.util.InsertionOrderUtil;
+
+import com.google.common.collect.ImmutableList;
+
+public class AdjacentEdgesQuery extends ConditionQuery {
+
+ private Id ownerVertex;
+ private Directions direction;
+ private Id[] edgeLabels;
+
+ private List<Condition> selfConditions;
+
+ private static final Id[] EMPTY = new Id[0];
+
+ public AdjacentEdgesQuery(Id ownerVertex, Directions direction) {
+ this(ownerVertex, direction, EMPTY);
+ }
+
+ public AdjacentEdgesQuery(Id ownerVertex, Directions direction,
+ Id[] edgeLabels) {
+ super(HugeType.EDGE);
+ E.checkArgument(ownerVertex != null,
+ "The edge query must contain source vertex");
+ E.checkArgument(direction != null,
+ "The edge query must contain direction");
+ this.ownerVertex = ownerVertex;
+ this.direction = direction;
+ this.edgeLabels = edgeLabels;
+ this.selfConditions = null;
+ }
+
+ @Override
+ public int conditionsSize() {
+ int size = super.conditionsSize() + 2;
+ if (this.edgeLabels.length > 0) {
+ size += 1;
+ }
+ return size;
+ }
+
+ @Override
+ public ConditionQuery query(Condition condition) {
+ if (!condition.isRelation()) {
+ return super.query(condition);
+ }
+
+ // Reset this.selfConditions cache
+ this.selfConditions = null;
+
+ // Update condition fields
+ Relation relation = ((Condition.Relation) condition);
+ Object key = relation.key();
+ RelationType relationType = relation.relation();
+
+ if (key == HugeKeys.OWNER_VERTEX) {
+ this.ownerVertex = (Id) relation.value();
+ return this;
+ }
+ if (key == HugeKeys.DIRECTION) {
+ this.direction = (Directions) relation.value();
+ return this;
+ }
+ if (key == HugeKeys.LABEL) {
+ Collection<Id> labels = null;
+ if (relationType == RelationType.EQ) {
+ labels = ImmutableList.of((Id) relation.value());
+ } else if (relationType == RelationType.IN) {
+ @SuppressWarnings("unchecked")
+ Collection<Id> value = (Collection<Id>) relation.value();
+ labels = value;
+ } else {
+ E.checkArgument(false,
+ "Unexpected relation type '%s' for '%s'",
+ relationType, key);
+ }
+
+ if (this.edgeLabels.length == 0) {
+ this.edgeLabels = labels.toArray(new Id[0]);
+ } else {
+ Collection<Id> edgeLabels = CollectionUtil.intersect(
+ Arrays.asList(this.edgeLabels),
+ labels);
+ if (edgeLabels.isEmpty()) {
+ // Returns empty result if conditions are conflicting
+ this.limit(0L);
+ }
+ this.edgeLabels = edgeLabels.toArray(new Id[0]);
+ }
+ return this;
+ }
+
+ return super.query(condition);
+ }
+
+ @Override
+ public Collection<Condition> conditions() {
+ List<Condition> conds = this.selfConditions();
+ if (super.conditionsSize() > 0) {
+ conds.addAll(super.conditions());
+ }
+ return conds;
+ }
+
+ private List<Condition> selfConditions() {
+ if (this.selfConditions != null) {
+ /*
+ * Return selfConditions cache if it has been collected before
+ * NOTE: it's also to keep the serialized condition value
+ */
+ return this.selfConditions;
+ }
+
+ List<Condition> conds = InsertionOrderUtil.newList();
+
+ conds.add(Condition.eq(HugeKeys.OWNER_VERTEX, this.ownerVertex));
+
+ if (this.direction == Directions.BOTH) {
+ conds.add(Condition.in(HugeKeys.DIRECTION, ImmutableList.of(
+ Directions.OUT,
+ Directions.IN)));
+ } else {
+ conds.add(Condition.eq(HugeKeys.DIRECTION, this.direction));
+ }
+
+ if (this.edgeLabels.length == 1) {
+ conds.add(Condition.eq(HugeKeys.LABEL, this.edgeLabels[0]));
+ } else if (this.edgeLabels.length > 1) {
+ conds.add(Condition.in(HugeKeys.LABEL,
+ Arrays.asList(this.edgeLabels)));
+ }
+
+ this.selfConditions = conds;
+ return conds;
+ }
+
+ @Override
+ public <T> T condition(Object key) {
+ T cond = this.selfCondition(key);
+ if (cond != null) {
+ return cond;
+ }
+ return super.condition(key);
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T> T selfCondition(Object key) {
+ if (key == HugeKeys.OWNER_VERTEX) {
+ return (T) this.ownerVertex;
+ }
+ if (key == HugeKeys.DIRECTION) {
+ return (T) this.direction;
+ }
+ if (key == HugeKeys.LABEL) {
+ if (this.edgeLabels.length == 0) {
+ return null;
+ }
+ if (this.edgeLabels.length == 1) {
+ return (T) this.edgeLabels[0];
+ }
+ E.checkState(false,
+ "Illegal key '%s' with more than one value", key);
+ }
+ return null;
+ }
+
+ private Condition.Relation selfRelation(Object key) {
+ if (key == HugeKeys.OWNER_VERTEX) {
+ return Condition.eq(HugeKeys.OWNER_VERTEX, this.ownerVertex);
+ }
+ if (key == HugeKeys.DIRECTION) {
+ if (this.direction == Directions.BOTH) {
+ return Condition.in(HugeKeys.DIRECTION, ImmutableList.of(
+ Directions.OUT,
+ Directions.IN));
+ } else {
+ return Condition.eq(HugeKeys.DIRECTION, this.direction);
+ }
+ }
+ if (key == HugeKeys.LABEL) {
+ if (this.edgeLabels.length == 0) {
+ return null;
+ }
+ if (this.edgeLabels.length == 1) {
+ return Condition.eq(HugeKeys.LABEL, this.edgeLabels[0]);
+ }
+ return Condition.in(HugeKeys.LABEL, Arrays.asList(this.edgeLabels));
+ }
+ return null;
+ }
+
+ @Override
+ public boolean containsCondition(HugeKeys key) {
+ if (key == HugeKeys.OWNER_VERTEX) {
+ return true;
+ }
+ if (key == HugeKeys.DIRECTION) {
+ return true;
+ }
+ if (key == HugeKeys.LABEL) {
+ if (this.edgeLabels.length == 0) {
+ return false;
+ }
+ return true;
+ }
+ return super.containsCondition(key);
+ }
+
+ @Override
+ public void unsetCondition(Object key) {
+ if (key == HugeKeys.OWNER_VERTEX ||
+ key == HugeKeys.DIRECTION ||
+ key == HugeKeys.LABEL) {
+ E.checkArgument(false, "Can't unset condition '%s'", key);
+ }
+ super.unsetCondition(key);
+ }
+
+ @Override
+ public List<Condition> syspropConditions() {
+ List<Condition> conds = this.selfConditions();
+ if (super.conditionsSize() > 0) {
+ conds.addAll(super.syspropConditions());
+ }
+ return conds;
+ }
+
+ @Override
+ public List<Condition> syspropConditions(HugeKeys key) {
+ Condition cond = this.selfRelation(key);
+ if (cond != null) {
+ return ImmutableList.of(cond);
+ }
+ return super.syspropConditions(key);
+ }
+
+ @Override
+ public List<Condition.Relation> relations() {
+ // NOTE: selfConditions() actually return a list of Relation
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ List<Condition.Relation> relations = (List) this.selfConditions();
+ if (super.conditionsSize() > 0) {
+ relations.addAll(super.relations());
+ }
+ return relations;
+ }
+
+ @Override
+ public Relation relation(Id key){
+ Relation relation = this.selfRelation(key);
+ if (relation != null) {
+ return relation;
+ }
+ return super.relation(key);
+ }
+
+ @Override
+ public boolean allSysprop() {
+ return super.allSysprop();
+ }
+
+ @Override
+ public boolean allRelation() {
+ if (!this.isFlattened()) {
+ return false;
+ }
+ return super.allRelation();
+ }
+
+ @Override
+ public AdjacentEdgesQuery copy() {
+ return (AdjacentEdgesQuery) super.copy();
+ }
+
+ @Override
+ public AdjacentEdgesQuery copyAndResetUnshared() {
+ return (AdjacentEdgesQuery) super.copyAndResetUnshared();
+ }
+
+ @Override
+ public boolean isFlattened() {
+ if (this.direction == Directions.BOTH) {
+ return false;
+ }
+ if (this.edgeLabels.length > 1) {
+ return false;
+ }
+ return super.isFlattened();
+ }
+
+ @Override
+ public boolean canFlatten() {
+ return super.conditionsSize() == 0;
+ }
+
+ @Override
+ public List<ConditionQuery> flatten() {
+ int labels = this.edgeLabels.length;
+ int directions = this.direction == Directions.BOTH ? 2 : 1;
+ int size = labels * directions;
+ List<ConditionQuery> queries = new ArrayList<>(size);
+ if (labels == 0) {
+ Id label = null;
+ if (this.direction == Directions.BOTH) {
+ queries.add(this.copyQuery(Directions.OUT, label));
+ queries.add(this.copyQuery(Directions.IN, label));
+ } else {
+ queries.add(this.copyQuery(this.direction, label));
+ }
+ } else {
+ for (Id label : this.edgeLabels) {
+ if (this.direction == Directions.BOTH) {
+ queries.add(this.copyQuery(Directions.OUT, label));
+ queries.add(this.copyQuery(Directions.IN, label));
+ } else {
+ queries.add(this.copyQuery(this.direction, label));
+ }
+ }
+ }
+ E.checkState(super.conditionsSize() == 0,
+ "Can't flatten query: %s", this);
+ return queries;
+ }
+
+ private AdjacentEdgesQuery copyQuery(Directions direction,
+ Id edgeLabel) {
+ AdjacentEdgesQuery query = this.copy();
+ query.direction = direction;
+ if (edgeLabel != null) {
+ query.edgeLabels = new Id[]{edgeLabel};
+ } else {
+ query.edgeLabels = EMPTY;
+ }
+ query.selfConditions = null;
+ return query;
+ }
+
+ @Override
+ public boolean test(HugeElement element) {
+ if (!super.test(element)) {
+ return false;
+ }
+ HugeEdge edge = (HugeEdge) element;
+ if (!edge.ownerVertex().id().equals(this.ownerVertex)) {
+ return false;
+ }
+ if (!edge.matchDirection(this.direction)) {
+ return false;
+ }
+
+ boolean matchedLabel = false;
+ if (this.edgeLabels.length == 0) {
+ matchedLabel = true;
+ } else {
+ for (Id label : this.edgeLabels) {
+ if (edge.schemaLabel().id().equals(label)) {
+ matchedLabel = true;
+ }
+ }
+ }
+ return matchedLabel;
+ }
+}
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Condition.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Condition.java
index 3ef9cd5..19d759c 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Condition.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Condition.java
@@ -345,31 +345,31 @@
return new SyspropRelation(key, RelationType.NEQ, value);
}
- public static Condition in(HugeKeys key, List<?> value) {
+ public static Relation in(HugeKeys key, List<?> value) {
return new SyspropRelation(key, RelationType.IN, value);
}
- public static Condition nin(HugeKeys key, List<?> value) {
+ public static Relation nin(HugeKeys key, List<?> value) {
return new SyspropRelation(key, RelationType.NOT_IN, value);
}
- public static Condition prefix(HugeKeys key, Id value) {
+ public static Relation prefix(HugeKeys key, Id value) {
return new SyspropRelation(key, RelationType.PREFIX, value);
}
- public static Condition containsValue(HugeKeys key, Object value) {
+ public static Relation containsValue(HugeKeys key, Object value) {
return new SyspropRelation(key, RelationType.CONTAINS_VALUE, value);
}
- public static Condition containsKey(HugeKeys key, Object value) {
+ public static Relation containsKey(HugeKeys key, Object value) {
return new SyspropRelation(key, RelationType.CONTAINS_KEY, value);
}
- public static Condition contains(HugeKeys key, Object value) {
+ public static Relation contains(HugeKeys key, Object value) {
return new SyspropRelation(key, RelationType.CONTAINS, value);
}
- public static Condition scan(String start, String end) {
+ public static Relation scan(String start, String end) {
Shard value = new Shard(start, end, 0);
return new SyspropRelation(HugeKeys.ID, RelationType.SCAN, value);
}
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQuery.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQuery.java
index 8a5706a..dfbfe75 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQuery.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQuery.java
@@ -37,6 +37,7 @@
import org.apache.hugegraph.backend.query.Condition.RelationType;
import org.apache.hugegraph.backend.query.serializer.QueryAdapter;
import org.apache.hugegraph.backend.query.serializer.QueryIdAdapter;
+import org.apache.hugegraph.exception.NotSupportException;
import org.apache.hugegraph.perf.PerfUtil.Watched;
import org.apache.hugegraph.structure.HugeElement;
import org.apache.hugegraph.structure.HugeProperty;
@@ -215,6 +216,10 @@
}
public List<Condition.Relation> relations() {
+ return this.selfRelations();
+ }
+
+ private List<Condition.Relation> selfRelations() {
List<Condition.Relation> relations = new ArrayList<>();
for (Condition c : this.conditions) {
relations.addAll(c.relations());
@@ -447,7 +452,7 @@
public List<Relation> userpropRelations() {
List<Relation> relations = new ArrayList<>();
- for (Relation r : this.relations()) {
+ for (Relation r : this.selfRelations()) {
if (!r.isSysprop()) {
relations.add(r);
}
@@ -456,12 +461,16 @@
}
public void resetUserpropConditions() {
+ if (this.conditions.isEmpty()) {
+ // UnsupprotedOperationException when ImmutableList.removeIf()
+ return;
+ }
this.conditions.removeIf(condition -> !condition.isSysprop());
}
public Set<Id> userpropKeys() {
Set<Id> keys = new LinkedHashSet<>();
- for (Relation r : this.relations()) {
+ for (Relation r : this.selfRelations()) {
if (!r.isSysprop()) {
Condition.UserpropRelation ur = (Condition.UserpropRelation) r;
keys.add(ur.key());
@@ -525,7 +534,7 @@
public boolean hasRangeCondition() {
// NOTE: we need to judge all the conditions, including the nested
- for (Condition.Relation r : this.relations()) {
+ for (Condition.Relation r : this.selfRelations()) {
if (r.relation().isRangeType()) {
return true;
}
@@ -535,7 +544,7 @@
public boolean hasSearchCondition() {
// NOTE: we need to judge all the conditions, including the nested
- for (Condition.Relation r : this.relations()) {
+ for (Condition.Relation r : this.selfRelations()) {
if (r.relation().isSearchType()) {
return true;
}
@@ -545,7 +554,7 @@
public boolean hasSecondaryCondition() {
// NOTE: we need to judge all the conditions, including the nested
- for (Condition.Relation r : this.relations()) {
+ for (Condition.Relation r : this.selfRelations()) {
if (r.relation().isSecondaryType()) {
return true;
}
@@ -555,7 +564,7 @@
public boolean hasNeqCondition() {
// NOTE: we need to judge all the conditions, including the nested
- for (Condition.Relation r : this.relations()) {
+ for (Condition.Relation r : this.selfRelations()) {
if (r.relation() == RelationType.NEQ) {
return true;
}
@@ -647,10 +656,19 @@
return false;
}
}
- return true;
+
+ return !this.mayHasDupKeys(ImmutableSet.of(HugeKeys.LABEL));
}
- public boolean mayHasDupKeys(Set<HugeKeys> keys) {
+ public boolean canFlatten() {
+ return false;
+ }
+
+ public List<ConditionQuery> flatten() {
+ throw new NotSupportException("ConditionQuery.flatten()");
+ }
+
+ private boolean mayHasDupKeys(Set<HugeKeys> keys) {
Map<HugeKeys, Integer> keyCounts = new HashMap<>();
for (Condition condition : this.conditions) {
if (!condition.isRelation()) {
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQueryFlatten.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQueryFlatten.java
index 83af41b..f4fd383 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQueryFlatten.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQueryFlatten.java
@@ -21,10 +21,10 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
+import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
-import java.util.stream.Collectors;
import org.apache.hugegraph.backend.id.Id;
import org.apache.hugegraph.backend.query.Condition.Relation;
@@ -35,24 +35,23 @@
import org.apache.hugegraph.util.NumericUtil;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
public final class ConditionQueryFlatten {
- private static final Set<HugeKeys> SPECIAL_KEYS = ImmutableSet.of(
- HugeKeys.LABEL
- );
-
public static List<ConditionQuery> flatten(ConditionQuery query) {
return flatten(query, false);
}
public static List<ConditionQuery> flatten(ConditionQuery query,
boolean supportIn) {
- if (query.isFlattened() && !query.mayHasDupKeys(SPECIAL_KEYS)) {
+ if (query.isFlattened()) {
return flattenRelations(query);
}
+ if (query.canFlatten()) {
+ return query.flatten();
+ }
+
List<ConditionQuery> queries = new ArrayList<>();
// Flatten IN/NOT_IN if needed
@@ -271,8 +270,10 @@
private static Relations optimizeRelations(Relations relations) {
// Optimize and-relations in one query
// e.g. (age>1 and age>2) -> (age>2)
- Set<Object> keys = relations.stream().map(Relation::key)
- .collect(Collectors.toSet());
+ Set<Object> keys = new HashSet<>(relations.size());
+ for (Relation r : relations) {
+ keys.add(r.key());
+ }
// No duplicated keys
if (keys.size() == relations.size()) {
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/EdgesQueryIterator.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/EdgesQueryIterator.java
index d8bce08..963f9f3 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/EdgesQueryIterator.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/EdgesQueryIterator.java
@@ -44,7 +44,7 @@
@Override
public boolean hasNext() {
- return sources.hasNext();
+ return this.sources.hasNext();
}
@Override
@@ -52,7 +52,7 @@
Id sourceId = this.sources.next();
ConditionQuery query = GraphTransaction.constructEdgesQuery(sourceId,
this.directions,
- this.labels.toArray(new Id[0]));
+ this.labels);
if (this.limit != Query.NO_LIMIT) {
query.limit(this.limit);
query.capacity(this.limit);
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphTransaction.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphTransaction.java
index e50fa5c..af7659f 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphTransaction.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphTransaction.java
@@ -46,6 +46,7 @@
import org.apache.hugegraph.backend.page.IdHolderList;
import org.apache.hugegraph.backend.page.PageInfo;
import org.apache.hugegraph.backend.page.QueryList;
+import org.apache.hugegraph.backend.query.AdjacentEdgesQuery;
import org.apache.hugegraph.backend.query.Aggregate;
import org.apache.hugegraph.backend.query.Aggregate.AggregateFunc;
import org.apache.hugegraph.backend.query.Condition;
@@ -1291,19 +1292,24 @@
@Watched
public static ConditionQuery constructEdgesQuery(Id sourceVertex,
Directions direction,
- Id... edgeLabels) {
- return constructEdgesQuery(sourceVertex, direction, List.of(edgeLabels));
+ List<Id> edgeLabels) {
+ return constructEdgesQuery(sourceVertex, direction,
+ edgeLabels.toArray(new Id[0]));
}
@Watched
public static ConditionQuery constructEdgesQuery(Id sourceVertex,
Directions direction,
- EdgeLabel... edgeLabels) {
+ Id... edgeLabels) {
E.checkState(sourceVertex != null,
"The edge query must contain source vertex");
E.checkState(direction != null,
"The edge query must contain direction");
+ if (true) {
+ return new AdjacentEdgesQuery(sourceVertex, direction, edgeLabels);
+ }
+
ConditionQuery query = new ConditionQuery(HugeType.EDGE);
// Edge source vertex
@@ -1321,52 +1327,9 @@
// Edge labels
if (edgeLabels.length == 1) {
- EdgeLabel edgeLabel = edgeLabels[0];
- if (edgeLabel.hasFather()) {
- query.eq(HugeKeys.LABEL, edgeLabel.fatherId());
- query.eq(HugeKeys.SUB_LABEL, edgeLabel.id());
- } else {
- query.eq(HugeKeys.LABEL, edgeLabel.id());
- }
- } else if (edgeLabels.length >= 1) {
- query.query(
- Condition.in(HugeKeys.LABEL,
- Arrays.stream(edgeLabels)
- .map(SchemaElement::id)
- .collect(Collectors.toList())));
- }
-
- return query;
- }
-
- private static ConditionQuery constructEdgesQuery(Id sourceVertex,
- Directions direction,
- List<Id> edgeLabels) {
- E.checkState(sourceVertex != null,
- "The edge query must contain source vertex");
- E.checkState(direction != null,
- "The edge query must contain direction");
-
- ConditionQuery query = new ConditionQuery(HugeType.EDGE);
-
- // Edge source vertex
- query.eq(HugeKeys.OWNER_VERTEX, sourceVertex);
-
- // Edge direction
- if (direction == Directions.BOTH) {
- query.query(Condition.or(
- Condition.eq(HugeKeys.DIRECTION, Directions.OUT),
- Condition.eq(HugeKeys.DIRECTION, Directions.IN)));
- } else {
- assert direction == Directions.OUT || direction == Directions.IN;
- query.eq(HugeKeys.DIRECTION, direction);
- }
-
- // Edge labels
- if (edgeLabels.size() == 1) {
- query.eq(HugeKeys.LABEL, edgeLabels.get(0));
- } else if (edgeLabels.size() > 1) {
- query.query(Condition.in(HugeKeys.LABEL, edgeLabels));
+ query.eq(HugeKeys.LABEL, edgeLabels[0]);
+ } else if (edgeLabels.length > 1) {
+ query.query(Condition.in(HugeKeys.LABEL, Arrays.asList(edgeLabels)));
}
return query;
@@ -1449,19 +1412,30 @@
private static void verifyEdgesConditionQuery(ConditionQuery query) {
assert query.resultType().isEdge();
+ if (query instanceof AdjacentEdgesQuery) {
+ return;
+ }
+
int total = query.conditionsSize();
- if (total == 1) {
+ boolean containsLabel = query.containsCondition(HugeKeys.LABEL);
+ boolean containsProps = query.containsCondition(HugeKeys.PROPERTIES);
+ boolean containsScan = query.containsScanRelation();
+
+ if (total == 1 && (containsLabel || containsProps || containsScan)) {
/*
* Supported query:
* 1.query just by edge label
* 2.query just by PROPERTIES (like containsKey, containsValue)
* 3.query with scan
*/
- if (query.containsCondition(HugeKeys.LABEL) ||
- query.containsCondition(HugeKeys.PROPERTIES) ||
- query.containsScanRelation()) {
- return;
- }
+ return;
+ }
+ if (total == 2 && (containsLabel && containsProps)) {
+ /*
+ * Supported query:
+ * query by edge label + PROPERTIES
+ */
+ return;
}
int matched = 0;
@@ -1472,19 +1446,11 @@
}
matched++;
}
- int count = matched;
-
- if (query.containsCondition(HugeKeys.PROPERTIES)) {
- matched++;
- if (count < 3 && query.containsCondition(HugeKeys.LABEL)) {
- matched++;
- }
- }
if (matched != total) {
throw new HugeException(
- "Not supported querying edges by %s, expect %s",
- query.conditions(), EdgeId.KEYS[count]);
+ "Not supported querying edges by %s, expect %s",
+ query.conditions(), EdgeId.KEYS[matched]);
}
}
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/HugeTraverser.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/HugeTraverser.java
index 8122c79..e1824fd 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/HugeTraverser.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/HugeTraverser.java
@@ -479,7 +479,7 @@
public Iterator<Edge> edgesOfVertex(Id source, Steps steps) {
List<Id> edgeLabels = steps.edgeLabels();
ConditionQuery cq = GraphTransaction.constructEdgesQuery(
- source, steps.direction(), edgeLabels.toArray(new Id[0]));
+ source, steps.direction(), edgeLabels);
cq.capacity(Query.NO_CAPACITY);
if (steps.limit() != NO_LIMIT) {
cq.limit(steps.limit());
diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeVertexStep.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeVertexStep.java
index bd2e138..3902846 100644
--- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeVertexStep.java
+++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeVertexStep.java
@@ -133,7 +133,7 @@
Id vertex = (Id) traverser.get().id();
Directions direction = Directions.convert(this.getDirection());
- EdgeLabel[] els = graph.mapElName2El(this.getEdgeLabels());
+ Id[] els = graph.mapElName2Id(this.getEdgeLabels());
LOG.debug("HugeVertexStep.edges(): vertex={}, direction={}, " +
"edgeLabels={}, has={}",
diff --git a/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/PerfExampleBase.java b/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/PerfExampleBase.java
index 6848666..dbba4bf 100644
--- a/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/PerfExampleBase.java
+++ b/hugegraph-server/hugegraph-example/src/main/java/org/apache/hugegraph/example/PerfExampleBase.java
@@ -31,6 +31,8 @@
import org.apache.hugegraph.backend.cache.CacheManager;
import org.apache.hugegraph.backend.id.Id;
import org.apache.hugegraph.backend.query.ConditionQuery;
+import org.apache.hugegraph.backend.query.Query;
+import org.apache.hugegraph.backend.tx.GraphTransaction;
import org.apache.hugegraph.perf.PerfUtil;
import org.apache.hugegraph.schema.SchemaManager;
import org.apache.hugegraph.structure.HugeVertex;
@@ -38,6 +40,7 @@
import org.apache.hugegraph.type.HugeType;
import org.apache.hugegraph.type.define.Directions;
import org.apache.hugegraph.type.define.HugeKeys;
+
import org.apache.hugegraph.util.Log;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.structure.Edge;
@@ -281,11 +284,9 @@
return this.hugegraph.vertices(id).next();
}
- public Iterator<Edge> queryVertexEdge(Object id, Directions direction) {
- ConditionQuery q = new ConditionQuery(HugeType.EDGE);
- q.eq(HugeKeys.OWNER_VERTEX, id);
- q.eq(HugeKeys.DIRECTION, direction);
- return this.hugegraph.edges(q);
+ public Iterator<Edge> queryVertexEdge(Object id, Directions dir) {
+ Query query = GraphTransaction.constructEdgesQuery((Id) id, dir, new Id[0]);
+ return this.hugegraph.edges(query);
}
}
}