This is an automated email from the ASF dual-hosted git repository. jermy pushed a commit to branch AdjacentEdgesQuery in repository https://gitbox.apache.org/repos/asf/incubator-hugegraph.git
commit 3f415e0591d1bd81d8c8faf573265f9c6b29f20e Author: Zhangmei Li <lizhang...@baidu.com> AuthorDate: Fri Dec 17 01:39:19 2021 +0800 add AdjacentEdgesQuery Change-Id: Ie7169fdb707495ff0a298ea97fa4d105117a132d --- .../backend/query/AdjacentEdgesQuery.java | 396 +++++++++++++++++++++ .../apache/hugegraph/backend/query/Condition.java | 14 +- .../hugegraph/backend/query/ConditionQuery.java | 34 +- .../backend/query/ConditionQueryFlatten.java | 19 +- .../backend/query/EdgesQueryIterator.java | 4 +- .../hugegraph/backend/tx/GraphTransaction.java | 81 ++--- .../traversal/algorithm/HugeTraverser.java | 2 +- .../traversal/optimize/HugeVertexStep.java | 2 +- .../apache/hugegraph/example/PerfExampleBase.java | 11 +- 9 files changed, 472 insertions(+), 91 deletions(-) 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 000000000..b1d3c1e41 --- /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 3ef9cd5fa..19d759c0b 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 @@ public abstract class Condition { 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 8a5706a77..dfbfe75eb 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.Relation; 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 class ConditionQuery extends IdQuery { } 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 class ConditionQuery extends IdQuery { 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 class ConditionQuery extends IdQuery { } 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 class ConditionQuery extends IdQuery { 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 class ConditionQuery extends IdQuery { 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 class ConditionQuery extends IdQuery { 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 class ConditionQuery extends IdQuery { 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 @@ public class ConditionQuery extends IdQuery { return false; } } - return true; + + return !this.mayHasDupKeys(ImmutableSet.of(HugeKeys.LABEL)); + } + + public boolean canFlatten() { + return false; + } + + public List<ConditionQuery> flatten() { + throw new NotSupportException("ConditionQuery.flatten()"); } - public boolean mayHasDupKeys(Set<HugeKeys> keys) { + 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 83af41b00..f4fd383ea 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.ArrayList; 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.InsertionOrderUtil; 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 @@ public final class ConditionQueryFlatten { 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 d8bce082c..963f9f3f8 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 @@ public class EdgesQueryIterator implements Iterator<Query> { @Override public boolean hasNext() { - return sources.hasNext(); + return this.sources.hasNext(); } @Override @@ -52,7 +52,7 @@ public class EdgesQueryIterator implements Iterator<Query> { 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 e50fa5c6f..8ef070c44 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.id.SplicingIdGenerator; 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; @@ -1298,55 +1299,16 @@ public class GraphTransaction extends IndexableTransaction { @Watched public static ConditionQuery constructEdgesQuery(Id sourceVertex, Directions direction, - EdgeLabel... edgeLabels) { + 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.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()))); + if (true) { + return new AdjacentEdgesQuery(sourceVertex, direction, edgeLabels); } - 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 @@ -1449,19 +1411,30 @@ public class GraphTransaction extends IndexableTransaction { 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 +1445,11 @@ public class GraphTransaction extends IndexableTransaction { } 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 8122c7908..e1824fd44 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 class HugeTraverser { 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 bd2e1388c..3902846f3 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 @@ public class HugeVertexStep<E extends Element> 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 684866674..dbba4bf96 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.Cache; 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.testutil.Whitebox; 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 @@ public abstract class PerfExampleBase { 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); } } }