Search in sources :

Example 6 with JanusGraphRelation

use of org.janusgraph.core.JanusGraphRelation in project janusgraph by JanusGraph.

the class BasicVertexCentricQueryBuilder method compileConstraints.

/**
 * Converts the constraint conditions of this query into a constraintMap which is passed as an argument.
 * If all the constraint conditions could be accounted for in the constraintMap, this method returns true, else -
 * if some constraints cannot be captured in an interval - it returns false to indicate that further in-memory
 * filtering will be necessary.
 * </p>
 * This constraint map is used in constructing the SliceQueries and query optimization since this representation
 * is easier to handle.
 *
 * @param conditions
 * @param constraintMap
 * @return
 */
private boolean compileConstraints(And<JanusGraphRelation> conditions, Map<RelationType, Interval> constraintMap) {
    boolean isFitted = true;
    for (Condition<JanusGraphRelation> condition : conditions.getChildren()) {
        RelationType type = null;
        Interval newInterval = null;
        if (condition instanceof Or) {
            Map.Entry<RelationType, Collection> orEqual = QueryUtil.extractOrCondition((Or) condition);
            if (orEqual != null) {
                type = orEqual.getKey();
                newInterval = new PointInterval(orEqual.getValue());
            }
        } else if (condition instanceof PredicateCondition) {
            PredicateCondition<RelationType, JanusGraphRelation> atom = (PredicateCondition) condition;
            type = atom.getKey();
            Interval interval = constraintMap.get(type);
            newInterval = intersectConstraints(interval, type, atom.getPredicate(), atom.getValue());
        }
        if (newInterval != null) {
            constraintMap.put(type, newInterval);
        } else
            isFitted = false;
    }
    if (adjacentVertex != null) {
        if (adjacentVertex.hasId()) {
            constraintMap.put(ImplicitKey.ADJACENT_ID, new PointInterval(adjacentVertex.longId()));
        } else
            isFitted = false;
    }
    return isFitted;
}
Also used : PredicateCondition(org.janusgraph.graphdb.query.condition.PredicateCondition) JanusGraphRelation(org.janusgraph.core.JanusGraphRelation) Or(org.janusgraph.graphdb.query.condition.Or) PointInterval(org.janusgraph.util.datastructures.PointInterval) SystemRelationType(org.janusgraph.graphdb.types.system.SystemRelationType) RelationType(org.janusgraph.core.RelationType) InternalRelationType(org.janusgraph.graphdb.internal.InternalRelationType) Collection(java.util.Collection) Map(java.util.Map) HashMap(java.util.HashMap) PointInterval(org.janusgraph.util.datastructures.PointInterval) Interval(org.janusgraph.util.datastructures.Interval) RangeInterval(org.janusgraph.util.datastructures.RangeInterval)

Example 7 with JanusGraphRelation

use of org.janusgraph.core.JanusGraphRelation in project janusgraph by JanusGraph.

the class AbstractVertex method remove.

/* ---------------------------------------------------------------
     * Changing Edges
	 * ---------------------------------------------------------------
	 */
@Override
public synchronized void remove() {
    verifyAccess();
    // if (isRemoved()) return; //Remove() is idempotent
    Iterator<JanusGraphRelation> iterator = it().query().noPartitionRestriction().relations().iterator();
    while (iterator.hasNext()) {
        iterator.next();
        iterator.remove();
    }
    // Remove all system types on the vertex
    for (JanusGraphRelation r : it().query().noPartitionRestriction().system().relations()) {
        r.remove();
    }
}
Also used : JanusGraphRelation(org.janusgraph.core.JanusGraphRelation)

Example 8 with JanusGraphRelation

use of org.janusgraph.core.JanusGraphRelation in project janusgraph by JanusGraph.

the class BasicVertexCentricQueryBuilder method executeRelations.

protected Iterable<JanusGraphRelation> executeRelations(InternalVertex vertex, BaseVertexCentricQuery baseQuery) {
    if (isPartitionedVertex(vertex)) {
        if (!hasAllCanonicalTypes()) {
            InternalVertex[] representatives = tx.getAllRepresentatives(vertex, restrict2Partitions);
            Iterable<JanusGraphRelation> merge = null;
            for (InternalVertex rep : representatives) {
                Iterable<JanusGraphRelation> iterable = executeIndividualRelations(rep, baseQuery);
                if (merge == null) {
                    merge = iterable;
                } else {
                    merge = ResultMergeSortIterator.mergeSort(merge, iterable, (Comparator) orders, false);
                }
            }
            return ResultSetIterator.wrap(merge, baseQuery.getLimit());
        } else
            vertex = tx.getCanonicalVertex(vertex);
    }
    return executeIndividualRelations(vertex, baseQuery);
}
Also used : JanusGraphRelation(org.janusgraph.core.JanusGraphRelation) InternalVertex(org.janusgraph.graphdb.internal.InternalVertex) Comparator(java.util.Comparator)

Example 9 with JanusGraphRelation

use of org.janusgraph.core.JanusGraphRelation in project janusgraph by JanusGraph.

the class BasicVertexCentricQueryBuilder method constructQueryWithoutProfile.

protected BaseVertexCentricQuery constructQueryWithoutProfile(RelationCategory returnType) {
    assert returnType != null;
    Preconditions.checkArgument(adjacentVertex == null || returnType == RelationCategory.EDGE, "Vertex constraints only apply to edges");
    if (limit <= 0)
        return BaseVertexCentricQuery.emptyQuery();
    // Prepare direction
    if (returnType == RelationCategory.PROPERTY) {
        if (dir == Direction.IN)
            return BaseVertexCentricQuery.emptyQuery();
        dir = Direction.OUT;
    }
    // Prepare order
    orders.makeImmutable();
    assert orders.hasCommonOrder();
    // Prepare constraints
    And<JanusGraphRelation> conditions = QueryUtil.constraints2QNF(tx, constraints);
    if (conditions == null)
        return BaseVertexCentricQuery.emptyQuery();
    // Don't be smart with query limit adjustments - it just messes up the caching layer and
    // penalizes when appropriate limits are set by the user!
    int sliceLimit = limit;
    // Construct (optimal) SliceQueries
    EdgeSerializer serializer = tx.getEdgeSerializer();
    List<BackendQueryHolder<SliceQuery>> queries;
    if (!hasTypes()) {
        final BackendQueryHolder<SliceQuery> query = new BackendQueryHolder<>(serializer.getQuery(returnType, querySystem), (adjacentVertex == null && dir == Direction.BOTH || returnType == RelationCategory.PROPERTY && dir == Direction.OUT) && !conditions.hasChildren(), orders.isEmpty());
        if (sliceLimit != Query.NO_LIMIT && sliceLimit < Integer.MAX_VALUE / 3) {
            // half will be filtered
            if (dir != Direction.BOTH && (returnType == RelationCategory.EDGE || returnType == RelationCategory.RELATION)) {
                sliceLimit *= 2;
            }
        }
        query.getBackendQuery().setLimit(computeLimit(conditions.size(), sliceLimit));
        queries = ImmutableList.of(query);
        conditions.add(returnType);
        conditions.add(new VisibilityFilterCondition<>(// Need this to filter out newly created invisible relations in the transaction
        querySystem ? VisibilityFilterCondition.Visibility.SYSTEM : VisibilityFilterCondition.Visibility.NORMAL));
    } else {
        final Set<RelationType> ts = new HashSet<>(types.length);
        queries = new ArrayList<>(types.length + 2);
        final Map<RelationType, Interval> intervalConstraints = new HashMap<>(conditions.size());
        final boolean isIntervalFittedConditions = compileConstraints(conditions, intervalConstraints);
        for (Interval pint : intervalConstraints.values()) {
            // Check if one of the constraints leads to an empty result set
            if (pint.isEmpty())
                return BaseVertexCentricQuery.emptyQuery();
        }
        for (String typeName : types) {
            InternalRelationType type = QueryUtil.getType(tx, typeName);
            if (type == null)
                continue;
            Preconditions.checkArgument(!querySystem || (type instanceof SystemRelationType), "Can only query for system types: %s", type);
            if (type instanceof ImplicitKey) {
                throw new UnsupportedOperationException("Implicit types are not supported in complex queries: " + type);
            }
            ts.add(type);
            Direction typeDir = dir;
            if (type.isPropertyKey()) {
                Preconditions.checkArgument(returnType != RelationCategory.EDGE, "Querying for edges but including a property key: %s", type.name());
                returnType = RelationCategory.PROPERTY;
                typeDir = Direction.OUT;
            }
            if (type.isEdgeLabel()) {
                Preconditions.checkArgument(returnType != RelationCategory.PROPERTY, "Querying for properties but including an edge label: %s", type.name());
                returnType = RelationCategory.EDGE;
                if (!type.isUnidirected(Direction.BOTH)) {
                    // Make sure unidirectionality lines up
                    if (typeDir == Direction.BOTH) {
                        if (type.isUnidirected(Direction.OUT))
                            typeDir = Direction.OUT;
                        else
                            typeDir = Direction.IN;
                    } else // Directions are incompatible
                    if (!type.isUnidirected(typeDir))
                        continue;
                }
            }
            if (type.isEdgeLabel() && typeDir == Direction.BOTH && intervalConstraints.isEmpty() && orders.isEmpty()) {
                // TODO: This if-condition is a little too restrictive - we also want to include those cases where
                // there ARE intervalConstraints or orders but those cannot be covered by any sort-keys
                SliceQuery q = serializer.getQuery(type, typeDir, null);
                q.setLimit(sliceLimit);
                queries.add(new BackendQueryHolder<>(q, isIntervalFittedConditions, true));
            } else {
                // Optimize for each direction independently
                Direction[] dirs = { typeDir };
                if (typeDir == Direction.BOTH) {
                    if (type.isEdgeLabel())
                        dirs = new Direction[] { Direction.OUT, Direction.IN };
                    else
                        // property key
                        dirs = new Direction[] { Direction.OUT };
                }
                for (Direction direction : dirs) {
                    /*
                        Find best scoring relation type to answer this query with. We score each candidate by the number
                        of conditions that each sort-keys satisfy. Equality conditions score higher than interval
                        conditions since they are more restrictive. We assign additional points if the sort key
                        satisfies the order of this query.
                        */
                    InternalRelationType bestCandidate = null;
                    double bestScore = Double.NEGATIVE_INFINITY;
                    boolean bestCandidateSupportsOrder = false;
                    PropertyKey[] bestCandidateExtendedSortKey = null;
                    for (InternalRelationType candidate : type.getRelationIndexes()) {
                        // Filter out those that don't apply
                        if (!candidate.isUnidirected(Direction.BOTH) && !candidate.isUnidirected(direction)) {
                            continue;
                        }
                        if (!candidate.equals(type) && candidate.getStatus() != SchemaStatus.ENABLED)
                            continue;
                        boolean supportsOrder = orders.isEmpty() || orders.getCommonOrder() == candidate.getSortOrder();
                        int currentOrder = 0;
                        double score = 0.0;
                        PropertyKey[] extendedSortKey = getExtendedSortKey(candidate, direction, tx);
                        for (PropertyKey keyType : extendedSortKey) {
                            if (currentOrder < orders.size() && orders.getKey(currentOrder).equals(keyType))
                                currentOrder++;
                            Interval interval = intervalConstraints.get(keyType);
                            if (interval == null || !interval.isPoints()) {
                                if (interval != null)
                                    score += 1;
                                break;
                            } else {
                                assert interval.isPoints();
                                score += 5.0 / interval.getPoints().size();
                            }
                        }
                        if (supportsOrder && currentOrder == orders.size())
                            score += 3;
                        if (score > bestScore) {
                            bestScore = score;
                            bestCandidate = candidate;
                            bestCandidateSupportsOrder = supportsOrder && currentOrder == orders.size();
                            bestCandidateExtendedSortKey = extendedSortKey;
                        }
                    }
                    Preconditions.checkArgument(bestCandidate != null, "Current graph schema does not support the specified query constraints for type: %s", type.name());
                    // Construct sort key constraints for the best candidate and then serialize into a SliceQuery
                    // that is wrapped into a BackendQueryHolder
                    EdgeSerializer.TypedInterval[] sortKeyConstraints = new EdgeSerializer.TypedInterval[bestCandidateExtendedSortKey.length];
                    constructSliceQueries(bestCandidateExtendedSortKey, sortKeyConstraints, 0, bestCandidate, direction, intervalConstraints, sliceLimit, isIntervalFittedConditions, bestCandidateSupportsOrder, queries);
                }
            }
        }
        if (queries.isEmpty())
            return BaseVertexCentricQuery.emptyQuery();
        conditions.add(getTypeCondition(ts));
    }
    return new BaseVertexCentricQuery(QueryUtil.simplifyAnd(conditions), dir, queries, orders, limit);
}
Also used : HashMap(java.util.HashMap) Direction(org.apache.tinkerpop.gremlin.structure.Direction) SystemRelationType(org.janusgraph.graphdb.types.system.SystemRelationType) RelationType(org.janusgraph.core.RelationType) InternalRelationType(org.janusgraph.graphdb.internal.InternalRelationType) EdgeSerializer(org.janusgraph.graphdb.database.EdgeSerializer) ImplicitKey(org.janusgraph.graphdb.types.system.ImplicitKey) HashSet(java.util.HashSet) JanusGraphRelation(org.janusgraph.core.JanusGraphRelation) SliceQuery(org.janusgraph.diskstorage.keycolumnvalue.SliceQuery) SystemRelationType(org.janusgraph.graphdb.types.system.SystemRelationType) BackendQueryHolder(org.janusgraph.graphdb.query.BackendQueryHolder) InternalRelationType(org.janusgraph.graphdb.internal.InternalRelationType) PropertyKey(org.janusgraph.core.PropertyKey) PointInterval(org.janusgraph.util.datastructures.PointInterval) Interval(org.janusgraph.util.datastructures.Interval) RangeInterval(org.janusgraph.util.datastructures.RangeInterval)

Example 10 with JanusGraphRelation

use of org.janusgraph.core.JanusGraphRelation in project janusgraph by JanusGraph.

the class RelationIdentifierUtils method findRelation.

protected static JanusGraphRelation findRelation(RelationIdentifier rId, JanusGraphTransaction tx) {
    JanusGraphVertex v = ((StandardJanusGraphTx) tx).getInternalVertex(rId.getOutVertexId());
    if (v == null || v.isRemoved())
        return null;
    JanusGraphVertex typeVertex = tx.getVertex(rId.getTypeId());
    if (typeVertex == null)
        return null;
    if (!(typeVertex instanceof RelationType))
        throw new IllegalArgumentException("Invalid RelationIdentifier: typeID does not reference a type");
    Iterable<? extends JanusGraphRelation> relations = getJanusGraphRelations(rId, tx, v, (RelationType) typeVertex);
    for (JanusGraphRelation r : relations) {
        // Find current or previous relation
        if (r.longId() == rId.getRelationId() || ((r instanceof StandardRelation) && ((StandardRelation) r).getPreviousID() == rId.getRelationId()))
            return r;
    }
    return null;
}
Also used : JanusGraphRelation(org.janusgraph.core.JanusGraphRelation) JanusGraphVertex(org.janusgraph.core.JanusGraphVertex) StandardJanusGraphTx(org.janusgraph.graphdb.transaction.StandardJanusGraphTx) RelationType(org.janusgraph.core.RelationType) InternalRelationType(org.janusgraph.graphdb.internal.InternalRelationType)

Aggregations

JanusGraphRelation (org.janusgraph.core.JanusGraphRelation)11 JanusGraphVertex (org.janusgraph.core.JanusGraphVertex)6 RelationType (org.janusgraph.core.RelationType)5 InternalRelationType (org.janusgraph.graphdb.internal.InternalRelationType)4 HashMap (java.util.HashMap)2 Direction (org.apache.tinkerpop.gremlin.structure.Direction)2 Edge (org.apache.tinkerpop.gremlin.structure.Edge)2 VertexProperty (org.apache.tinkerpop.gremlin.structure.VertexProperty)2 JanusGraphEdge (org.janusgraph.core.JanusGraphEdge)2 JanusGraphTransaction (org.janusgraph.core.JanusGraphTransaction)2 JanusGraphVertexProperty (org.janusgraph.core.JanusGraphVertexProperty)2 PropertyKey (org.janusgraph.core.PropertyKey)2 PredicateCondition (org.janusgraph.graphdb.query.condition.PredicateCondition)2 StandardJanusGraphTx (org.janusgraph.graphdb.transaction.StandardJanusGraphTx)2 SystemRelationType (org.janusgraph.graphdb.types.system.SystemRelationType)2 Interval (org.janusgraph.util.datastructures.Interval)2 PointInterval (org.janusgraph.util.datastructures.PointInterval)2 RangeInterval (org.janusgraph.util.datastructures.RangeInterval)2 Test (org.junit.jupiter.api.Test)2 LongArrayList (com.carrotsearch.hppc.LongArrayList)1