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 c9cca52663..0fe2c12192 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 @@ -589,6 +589,23 @@ public ConditionQuery copyAndResetUnshared() { return query; } + public Condition.Relation copyRelationAndUpdateQuery(Object key) { + Condition.Relation copyRes = null; + for (int i = 0; i < this.conditions.size(); i++) { + Condition c = this.conditions.get(i); + if (c.isRelation()) { + Condition.Relation r = (Condition.Relation) c; + if (r.key().equals(key)) { + copyRes = r.copy(); + this.conditions.set(i, copyRes); + break; + } + } + } + E.checkArgument(copyRes != null, "Failed to copy Condition.Relation: %s", key); + return copyRes; + } + @Override public boolean test(HugeElement element) { if (!this.ids().isEmpty() && !super.test(element)) { 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 5fe3dec37b..10aa73f719 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 @@ -29,6 +29,7 @@ import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; +import java.util.stream.Collectors; import org.apache.commons.collections.CollectionUtils; import org.apache.hugegraph.HugeException; @@ -1447,8 +1448,7 @@ private QueryList optimizeQueries(Query query, private Query optimizeQuery(ConditionQuery query) { if (query.idsSize() > 0) { - throw new HugeException( - "Not supported querying by id and conditions: %s", query); + throw new HugeException("Not supported querying by id and conditions: %s", query); } Id label = query.condition(HugeKeys.LABEL); @@ -1468,11 +1468,10 @@ private Query optimizeQuery(ConditionQuery query) { String primaryValues = query.userpropValuesString(keys); LOG.debug("Query vertices by primaryKeys: {}", query); // Convert {vertex-label + primary-key} to vertex-id - Id id = SplicingIdGenerator.splicing(label.asString(), - primaryValues); + Id id = SplicingIdGenerator.splicing(label.asString(), primaryValues); /* - * Just query by primary-key(id), ignore other userprop(if - * exists) that it will be filtered by queryVertices(Query) + * Just query by primary-key(id), ignore other user-props(if exists) + * that it will be filtered by queryVertices(Query) */ return new IdQuery(query, id); } @@ -1482,25 +1481,60 @@ private Query optimizeQuery(ConditionQuery query) { // Optimize edge query if (query.resultType().isEdge() && label != null && query.condition(HugeKeys.OWNER_VERTEX) != null && - query.condition(HugeKeys.DIRECTION) != null && - matchEdgeSortKeys(query, false, this.graph())) { - // Query edge by sourceVertex + direction + label + sort-values - query.optimized(OptimizedType.SORT_KEYS); - query = query.copy(); - // Serialize sort-values - List keys = this.graph().edgeLabel(label).sortKeys(); - List conditions = - GraphIndexTransaction.constructShardConditions( - query, keys, HugeKeys.SORT_VALUES); - query.query(conditions); - /* - * Reset all userprop since transferred to sort-keys, ignore other - * userprop(if exists) that it will be filtered by queryEdges(Query) - */ - query.resetUserpropConditions(); + query.condition(HugeKeys.DIRECTION) != null) { + + Directions dir = query.condition(HugeKeys.DIRECTION); + EdgeLabel edgeLabel = this.graph().edgeLabel(label); + + if (query.containsRelation(HugeKeys.OWNER_VERTEX, Condition.RelationType.IN)) { + // For IN query, filter schema non-adjacent vertices. + ArrayList vertexIdList = query.condition(HugeKeys.OWNER_VERTEX); + List filterVertexList = vertexIdList.stream().filter(vertexId -> { + Vertex vertex = this.graph().vertex(vertexId); + VertexLabel vertexLabel = graph().vertexLabel(vertex.label()); + return edgeLabel.linkWithVertexLabel(vertexLabel.id(), dir); + }).collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(filterVertexList)) { + return new Query(query.resultType()); + } + + if (vertexIdList.size() != filterVertexList.size()) { + // Modify on the copied relation to avoid affecting other query + Condition.Relation relation = + query.copyRelationAndUpdateQuery(HugeKeys.OWNER_VERTEX); + relation.value(filterVertexList); + } + } else if (query.containsRelation(HugeKeys.OWNER_VERTEX, Condition.RelationType.EQ)) { + Id vertexId = query.condition(HugeKeys.OWNER_VERTEX); + Vertex vertex = QueryResults.one(this.queryVertices(vertexId)); + if (vertex != null) { + VertexLabel vertexLabel = graph().vertexLabel(vertex.label()); + // For EQ query, just skip query storage if adjacent schema doesn't exist + if (!edgeLabel.linkWithVertexLabel(vertexLabel.id(), dir)) { + return new Query(query.resultType()); + } + } + } - LOG.debug("Query edges by sortKeys: {}", query); - return query; + if (matchEdgeSortKeys(query, false, this.graph())) { + // Query edge by sourceVertex + direction + label + sort-values + query.optimized(OptimizedType.SORT_KEYS); + query = query.copy(); + // Serialize sort-values + List keys = this.graph().edgeLabel(label).sortKeys(); + List conditions = GraphIndexTransaction + .constructShardConditions(query, keys, HugeKeys.SORT_VALUES); + query.query(conditions); + /* + * Reset all userprop since transferred to sort-keys, ignore other + * userprop(if exists) that it will be filtered by queryEdges(Query) + */ + query.resetUserpropConditions(); + + LOG.debug("Query edges by sortKeys: {}", query); + return query; + } } /* diff --git a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/EdgeLabel.java b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/EdgeLabel.java index 8a9b184e24..b9fac4643a 100644 --- a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/EdgeLabel.java +++ b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/schema/EdgeLabel.java @@ -31,6 +31,7 @@ import org.apache.hugegraph.backend.id.IdGenerator; import org.apache.hugegraph.schema.builder.SchemaBuilder; import org.apache.hugegraph.type.HugeType; +import org.apache.hugegraph.type.define.Directions; import org.apache.hugegraph.type.define.EdgeLabelType; import org.apache.hugegraph.type.define.Frequency; import org.apache.hugegraph.type.define.SchemaStatus; @@ -110,6 +111,17 @@ public boolean linkWithLabel(Id id) { return this.sourceLabel.equals(id) || this.targetLabel.equals(id); } + public boolean linkWithVertexLabel(Id label, Directions dir) { + if (dir.equals(Directions.IN)) { + return this.targetLabel.equals(label); + } else if (dir.equals(Directions.OUT)) { + return this.sourceLabel.equals(label); + } else if (dir.equals(Directions.BOTH)) { + return this.targetLabel.equals(label) || this.sourceLabel.equals(label); + } + return false; + } + public boolean checkLinkEqual(Id sourceLabel, Id targetLabel) { return this.sourceLabel.equals(sourceLabel) && this.targetLabel.equals(targetLabel); diff --git a/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/cmd/InitStore.java b/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/cmd/InitStore.java index e226e381fb..255528932e 100644 --- a/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/cmd/InitStore.java +++ b/hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/cmd/InitStore.java @@ -98,14 +98,14 @@ private static HugeGraph initGraph(String configPath) throws Exception { try { BackendStoreInfo backendStoreInfo = graph.backendStoreInfo(); if (backendStoreInfo.exists()) { - LOG.info("Skip init-store due to the backend store of '{}' " + - "had been initialized", graph.name()); backendStoreInfo.checkVersion(); /* * Init the required information for creating the admin account * (when switch from non-auth mode to auth mode) */ graph.initSystemInfo(); + LOG.info("Skip init-store due to the backend store of '{}' " + + "had been initialized", graph.name()); } else { initBackend(graph); }