Search in sources :

Example 1 with SystemRelationType

use of com.thinkaurelius.titan.graphdb.types.system.SystemRelationType in project titan by thinkaurelius.

the class BaseVertexCentricQueryBuilder method orderBy.

@Override
public Q orderBy(String keyName, org.apache.tinkerpop.gremlin.process.traversal.Order order) {
    Preconditions.checkArgument(schemaInspector.containsPropertyKey(keyName), "Provided key does not exist: %s", keyName);
    PropertyKey key = schemaInspector.getPropertyKey(keyName);
    Preconditions.checkArgument(key != null && order != null, "Need to specify and key and an order");
    Preconditions.checkArgument(Comparable.class.isAssignableFrom(key.dataType()), "Can only order on keys with comparable data type. [%s] has datatype [%s]", key.name(), key.dataType());
    Preconditions.checkArgument(key.cardinality() == Cardinality.SINGLE, "Ordering is undefined on multi-valued key [%s]", key.name());
    Preconditions.checkArgument(!(key instanceof SystemRelationType), "Cannot use system types in ordering: %s", key);
    Preconditions.checkArgument(!orders.containsKey(key));
    Preconditions.checkArgument(orders.isEmpty(), "Only a single sort order is supported on vertex queries");
    orders.add(key, Order.convert(order));
    return getThis();
}
Also used : SystemRelationType(com.thinkaurelius.titan.graphdb.types.system.SystemRelationType) PropertyKey(com.thinkaurelius.titan.core.PropertyKey)

Example 2 with SystemRelationType

use of com.thinkaurelius.titan.graphdb.types.system.SystemRelationType in project titan by thinkaurelius.

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<TitanRelation> 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()) {
        BackendQueryHolder<SliceQuery> query = new BackendQueryHolder<SliceQuery>(serializer.getQuery(returnType, querySystem), ((dir == Direction.BOTH || (returnType == RelationCategory.PROPERTY && dir == Direction.OUT)) && !conditions.hasChildren()), orders.isEmpty());
        if (sliceLimit != Query.NO_LIMIT && sliceLimit < Integer.MAX_VALUE / 3) {
            //If only one direction is queried, ask for twice the limit from backend since approximately 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 //Need this to filter out newly created invisible relations in the transaction
        VisibilityFilterCondition<TitanRelation>(querySystem ? VisibilityFilterCondition.Visibility.SYSTEM : VisibilityFilterCondition.Visibility.NORMAL));
    } else {
        Set<RelationType> ts = new HashSet<RelationType>(types.length);
        queries = new ArrayList<BackendQueryHolder<SliceQuery>>(types.length + 2);
        Map<RelationType, Interval> intervalConstraints = new HashMap<RelationType, Interval>(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()) {
                if (returnType == RelationCategory.EDGE)
                    throw new IllegalArgumentException("Querying for edges but including a property key: " + type.name());
                returnType = RelationCategory.PROPERTY;
                typeDir = Direction.OUT;
            }
            if (type.isEdgeLabel()) {
                if (returnType == RelationCategory.PROPERTY)
                    throw new IllegalArgumentException("Querying for properties but including an edge label: " + 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<SliceQuery>(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;
                    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() ? true : orders.getCommonOrder() == candidate.getSortOrder();
                        int currentOrder = 0;
                        double score = 0.0;
                        PropertyKey[] extendedSortKey = getExtendedSortKey(candidate, direction, tx);
                        for (int i = 0; i < extendedSortKey.length; i++) {
                            PropertyKey keyType = extendedSortKey[i];
                            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();
                        }
                    }
                    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
                    PropertyKey[] extendedSortKey = getExtendedSortKey(bestCandidate, direction, tx);
                    EdgeSerializer.TypedInterval[] sortKeyConstraints = new EdgeSerializer.TypedInterval[extendedSortKey.length];
                    constructSliceQueries(extendedSortKey, sortKeyConstraints, 0, bestCandidate, direction, intervalConstraints, sliceLimit, isIntervalFittedConditions, bestCandidateSupportsOrder, queries);
                }
            }
        }
        if (queries.isEmpty())
            return BaseVertexCentricQuery.emptyQuery();
        conditions.add(getTypeCondition(ts));
    }
    return new BaseVertexCentricQuery(QueryUtil.simplifyQNF(conditions), dir, queries, orders, limit);
}
Also used : Direction(org.apache.tinkerpop.gremlin.structure.Direction) SystemRelationType(com.thinkaurelius.titan.graphdb.types.system.SystemRelationType) EdgeSerializer(com.thinkaurelius.titan.graphdb.database.EdgeSerializer) ImplicitKey(com.thinkaurelius.titan.graphdb.types.system.ImplicitKey) SliceQuery(com.thinkaurelius.titan.diskstorage.keycolumnvalue.SliceQuery) SystemRelationType(com.thinkaurelius.titan.graphdb.types.system.SystemRelationType) Interval(com.thinkaurelius.titan.util.datastructures.Interval) PointInterval(com.thinkaurelius.titan.util.datastructures.PointInterval) RangeInterval(com.thinkaurelius.titan.util.datastructures.RangeInterval)

Aggregations

SystemRelationType (com.thinkaurelius.titan.graphdb.types.system.SystemRelationType)2 PropertyKey (com.thinkaurelius.titan.core.PropertyKey)1 SliceQuery (com.thinkaurelius.titan.diskstorage.keycolumnvalue.SliceQuery)1 EdgeSerializer (com.thinkaurelius.titan.graphdb.database.EdgeSerializer)1 ImplicitKey (com.thinkaurelius.titan.graphdb.types.system.ImplicitKey)1 Interval (com.thinkaurelius.titan.util.datastructures.Interval)1 PointInterval (com.thinkaurelius.titan.util.datastructures.PointInterval)1 RangeInterval (com.thinkaurelius.titan.util.datastructures.RangeInterval)1 Direction (org.apache.tinkerpop.gremlin.structure.Direction)1