Search in sources :

Example 21 with SliceQuery

use of com.thinkaurelius.titan.diskstorage.keycolumnvalue.SliceQuery in project titan by thinkaurelius.

the class AbstractVertexCentricQueryBuilder method constructQuery.

protected BaseVertexCentricQuery constructQuery(RelationType returnType) {
    assert returnType != null;
    if (limit == 0)
        return BaseVertexCentricQuery.emptyQuery();
    // Prepare direction
    if (returnType == RelationType.PROPERTY) {
        if (dir == Direction.IN)
            return BaseVertexCentricQuery.emptyQuery();
        dir = Direction.OUT;
    }
    assert getVertexConstraint() == null || returnType == RelationType.EDGE;
    // Prepare constraints
    And<TitanRelation> conditions = QueryUtil.constraints2QNF(tx, constraints);
    if (conditions == null)
        return BaseVertexCentricQuery.emptyQuery();
    assert limit > 0;
    // 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), ((dir == Direction.BOTH || (returnType == RelationType.PROPERTY && dir == Direction.OUT)) && !conditions.hasChildren() && includeHidden), true, null);
        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 == RelationType.EDGE || returnType == RelationType.RELATION))
                sliceLimit *= 2;
            // on properties, add some for the hidden properties on a vertex
            if (!includeHidden && (returnType == RelationType.PROPERTY || returnType == RelationType.RELATION))
                sliceLimit += 3;
        }
        query.getBackendQuery().setLimit(computeLimit(conditions, sliceLimit));
        queries = ImmutableList.of(query);
        // Add remaining conditions that only apply if no type is defined
        if (!includeHidden)
            conditions.add(new HiddenFilterCondition<TitanRelation>());
        conditions.add(returnType);
    } else {
        Set<TitanType> ts = new HashSet<TitanType>(types.length);
        queries = new ArrayList<BackendQueryHolder<SliceQuery>>(types.length + 4);
        for (String typeName : types) {
            InternalType type = getType(typeName);
            if (type != null && (includeHidden || !type.isHidden())) {
                ts.add(type);
                if (type.isPropertyKey()) {
                    if (returnType == RelationType.EDGE)
                        throw new IllegalArgumentException("Querying for edges but including a property key: " + type.getName());
                    returnType = RelationType.PROPERTY;
                }
                if (type.isEdgeLabel()) {
                    if (returnType == RelationType.PROPERTY)
                        throw new IllegalArgumentException("Querying for properties but including an edge label: " + type.getName());
                    returnType = RelationType.EDGE;
                }
                // Construct sort key constraints (if any, and if not direction==Both)
                EdgeSerializer.TypedInterval[] sortKeyConstraints = new EdgeSerializer.TypedInterval[type.getSortKey().length];
                And<TitanRelation> remainingConditions = conditions;
                boolean vertexConstraintApplies = type.getSortKey().length == 0 || conditions.hasChildren();
                if (type.getSortKey().length > 0 && conditions.hasChildren()) {
                    remainingConditions = conditions.clone();
                    sortKeyConstraints = compileSortKeyConstraints(type, tx, remainingConditions);
                    // Constraints cannot be matched
                    if (sortKeyConstraints == null)
                        continue;
                    Interval interval;
                    if (sortKeyConstraints[sortKeyConstraints.length - 1] == null || (interval = sortKeyConstraints[sortKeyConstraints.length - 1].interval) == null || !interval.isPoint()) {
                        vertexConstraintApplies = false;
                    }
                }
                Direction[] dirs = { dir };
                EdgeSerializer.VertexConstraint vertexConstraint = getVertexConstraint();
                if (dir == Direction.BOTH && (hasSortKeyConstraints(sortKeyConstraints) || (vertexConstraintApplies && vertexConstraint != null))) {
                    // Split on direction in the presence of effective sort key constraints
                    dirs = new Direction[] { Direction.OUT, Direction.IN };
                }
                for (Direction dir : dirs) {
                    EdgeSerializer.VertexConstraint vertexCon = vertexConstraint;
                    if (vertexCon == null || !vertexConstraintApplies || type.isUnique(dir))
                        vertexCon = null;
                    EdgeSerializer.TypedInterval[] sortConstraints = sortKeyConstraints;
                    if (hasSortKeyConstraints(sortKeyConstraints) && type.isUnique(dir)) {
                        sortConstraints = new EdgeSerializer.TypedInterval[type.getSortKey().length];
                    }
                    boolean isFitted = !remainingConditions.hasChildren() && vertexConstraint == vertexCon && sortConstraints == sortKeyConstraints;
                    SliceQuery q = serializer.getQuery(type, dir, sortConstraints, vertexCon);
                    q.setLimit(computeLimit(remainingConditions, sliceLimit));
                    queries.add(new BackendQueryHolder<SliceQuery>(q, isFitted, true, null));
                }
            }
        }
        if (queries.isEmpty())
            return BaseVertexCentricQuery.emptyQuery();
        conditions.add(getTypeCondition(ts));
    }
    return new BaseVertexCentricQuery(QueryUtil.simplifyQNF(conditions), dir, queries, limit);
}
Also used : Direction(com.tinkerpop.blueprints.Direction) SliceQuery(com.thinkaurelius.titan.diskstorage.keycolumnvalue.SliceQuery) InternalType(com.thinkaurelius.titan.graphdb.internal.InternalType) EdgeSerializer(com.thinkaurelius.titan.graphdb.database.EdgeSerializer) PointInterval(com.thinkaurelius.titan.util.datastructures.PointInterval) Interval(com.thinkaurelius.titan.util.datastructures.Interval) ProperInterval(com.thinkaurelius.titan.util.datastructures.ProperInterval)

Example 22 with SliceQuery

use of com.thinkaurelius.titan.diskstorage.keycolumnvalue.SliceQuery in project titan by thinkaurelius.

the class MultiVertexCentricQueryBuilder method relations.

protected Map<TitanVertex, Iterable<? extends TitanRelation>> relations(RelationType returnType) {
    Preconditions.checkArgument(!vertices.isEmpty(), "Need to add at least one vertex to query");
    BaseVertexCentricQuery vq = super.constructQuery(returnType);
    Map<TitanVertex, Iterable<? extends TitanRelation>> result = new HashMap<TitanVertex, Iterable<? extends TitanRelation>>(vertices.size());
    if (!vq.isEmpty()) {
        for (BackendQueryHolder<SliceQuery> sq : vq.getQueries()) {
            tx.executeMultiQuery(vertices, sq.getBackendQuery());
        }
        Condition<TitanRelation> condition = vq.getCondition();
        for (InternalVertex v : vertices) {
            // Add other-vertex and direction related conditions
            And<TitanRelation> newcond = new And<TitanRelation>();
            if (condition instanceof And)
                newcond.addAll((And) condition);
            else
                newcond.add(condition);
            newcond.add(new DirectionCondition<TitanRelation>(v, getDirection()));
            VertexCentricQuery vqsingle = new VertexCentricQuery(v, newcond, vq.getDirection(), vq.getQueries(), vq.getLimit());
            result.put(v, new QueryProcessor<VertexCentricQuery, TitanRelation, SliceQuery>(vqsingle, tx.edgeProcessor));
        }
    } else {
        Iterable<? extends TitanRelation> emptyIter = IterablesUtil.emptyIterable();
        for (TitanVertex v : vertices) result.put(v, emptyIter);
    }
    return result;
}
Also used : HashMap(java.util.HashMap) SliceQuery(com.thinkaurelius.titan.diskstorage.keycolumnvalue.SliceQuery) And(com.thinkaurelius.titan.graphdb.query.condition.And) InternalVertex(com.thinkaurelius.titan.graphdb.internal.InternalVertex)

Aggregations

SliceQuery (com.thinkaurelius.titan.diskstorage.keycolumnvalue.SliceQuery)22 EntryList (com.thinkaurelius.titan.diskstorage.EntryList)6 StaticBuffer (com.thinkaurelius.titan.diskstorage.StaticBuffer)6 Interval (com.thinkaurelius.titan.util.datastructures.Interval)5 EdgeSerializer (com.thinkaurelius.titan.graphdb.database.EdgeSerializer)3 CacheVertex (com.thinkaurelius.titan.graphdb.vertices.CacheVertex)3 PointInterval (com.thinkaurelius.titan.util.datastructures.PointInterval)3 ArrayList (java.util.ArrayList)3 Map (java.util.Map)3 Direction (org.apache.tinkerpop.gremlin.structure.Direction)3 LongArrayList (com.carrotsearch.hppc.LongArrayList)2 TitanVertex (com.thinkaurelius.titan.core.TitanVertex)2 KeySliceQuery (com.thinkaurelius.titan.diskstorage.keycolumnvalue.KeySliceQuery)2 CacheTransaction (com.thinkaurelius.titan.diskstorage.keycolumnvalue.cache.CacheTransaction)2 ScanMetrics (com.thinkaurelius.titan.diskstorage.keycolumnvalue.scan.ScanMetrics)2 InternalVertex (com.thinkaurelius.titan.graphdb.internal.InternalVertex)2 ImplicitKey (com.thinkaurelius.titan.graphdb.types.system.ImplicitKey)2 RangeInterval (com.thinkaurelius.titan.util.datastructures.RangeInterval)2 Preconditions (com.google.common.base.Preconditions)1 ImmutableList (com.google.common.collect.ImmutableList)1