@Override public Iterator<TitanElement> getNew(final StandardElementQuery query) { Preconditions.checkArgument( query.getType() == StandardElementQuery.Type.VERTEX || query.getType() == StandardElementQuery.Type.EDGE); if (query.getType() == StandardElementQuery.Type.VERTEX && hasModifications()) { // Collect all keys from the query - ASSUMPTION: query is an AND of KeyAtom final Set<TitanKey> keys = Sets.newHashSet(); KeyAtom<TitanKey> standardIndexKey = null; for (KeyCondition<TitanKey> cond : query.getCondition().getChildren()) { KeyAtom<TitanKey> atom = (KeyAtom<TitanKey>) cond; if (atom.getRelation() == Cmp.EQUAL && isVertexIndexProperty(atom.getKey())) standardIndexKey = atom; keys.add(atom.getKey()); } Iterator<TitanVertex> vertices; if (standardIndexKey == null) { Set<TitanVertex> vertexSet = Sets.newHashSet(); for (TitanRelation r : addedRelations.getView( new Predicate<InternalRelation>() { @Override public boolean apply(@Nullable InternalRelation relation) { return keys.contains(relation.getType()); } })) { vertexSet.add(((TitanProperty) r).getVertex()); } for (TitanRelation r : deletedRelations.values()) { if (keys.contains(r.getType())) { TitanVertex v = ((TitanProperty) r).getVertex(); if (!v.isRemoved()) vertexSet.add(v); } } vertices = vertexSet.iterator(); } else { vertices = Iterators.transform( newVertexIndexEntries .get(standardIndexKey.getCondition(), standardIndexKey.getKey()) .iterator(), new Function<TitanProperty, TitanVertex>() { @Nullable @Override public TitanVertex apply(@Nullable TitanProperty o) { return o.getVertex(); } }); } return (Iterator) Iterators.filter( vertices, new Predicate<TitanVertex>() { @Override public boolean apply(@Nullable TitanVertex vertex) { return query.matches(vertex); } }); } else if (query.getType() == StandardElementQuery.Type.EDGE && !addedRelations.isEmpty()) { return (Iterator) addedRelations .getView( new Predicate<InternalRelation>() { @Override public boolean apply(@Nullable InternalRelation relation) { return (relation instanceof TitanEdge) && !relation.isHidden() && query.matches(relation); } }) .iterator(); } else throw new IllegalArgumentException("Unexpected type: " + query.getType()); }
@Override public Iterator<TitanElement> execute(final StandardElementQuery query) { Iterator<TitanElement> iter = null; if (!query.hasIndex()) { log.warn( "Query requires iterating over all vertices [{}]. For better performance, use indexes", query.getCondition()); if (query.getType() == StandardElementQuery.Type.VERTEX) { iter = (Iterator) getVertices().iterator(); } else if (query.getType() == StandardElementQuery.Type.EDGE) { iter = (Iterator) getEdges().iterator(); } else throw new IllegalArgumentException("Unexpected type: " + query.getType()); iter = Iterators.filter( iter, new Predicate<TitanElement>() { @Override public boolean apply(@Nullable TitanElement element) { return query.matches(element); } }); } else { String index = query.getIndex(); log.debug("Answering query [{}] with index {}", query, index); // Filter out everything not covered by the index KeyCondition<TitanKey> condition = query.getCondition(); // ASSUMPTION: query is an AND of KeyAtom Preconditions.checkArgument(condition instanceof KeyAnd); Preconditions.checkArgument(condition.hasChildren()); List<KeyCondition<TitanKey>> newConds = Lists.newArrayList(); boolean needsFilter = false; for (KeyCondition<TitanKey> c : condition.getChildren()) { KeyAtom<TitanKey> atom = (KeyAtom<TitanKey>) c; if (getGraph() .getIndexInformation(index) .supports(atom.getKey().getDataType(), atom.getRelation()) && atom.getKey().hasIndex(index, query.getType().getElementType()) && atom.getCondition() != null) { newConds.add(atom); } else { log.debug( "Filtered out atom [{}] from query [{}] because it is not indexed or not covered by the index"); needsFilter = true; } } Preconditions.checkArgument( !newConds.isEmpty(), "Invalid index assignment [%s] to query [%s]", index, query); final StandardElementQuery indexQuery; if (needsFilter) { Preconditions.checkArgument( !newConds.isEmpty(), "Query has been assigned an index [%s] in error: %s", query.getIndex(), query); indexQuery = new StandardElementQuery( query.getType(), KeyAnd.of(newConds.toArray(new KeyAtom[newConds.size()])), query.getLimit(), index); } else { indexQuery = query; } try { iter = Iterators.transform( indexCache .get( indexQuery, new Callable<List<Object>>() { @Override public List<Object> call() throws Exception { return graph.elementQuery(indexQuery, txHandle); } }) .iterator(), new Function<Object, TitanElement>() { @Nullable @Override public TitanElement apply(@Nullable Object id) { Preconditions.checkNotNull(id); if (id instanceof Long) return (TitanVertex) getVertex((Long) id); else if (id instanceof RelationIdentifier) return (TitanElement) getEdge((RelationIdentifier) id); else throw new IllegalArgumentException("Unexpected id type: " + id); } }); } catch (Exception e) { throw new TitanException("Could not call index", e); } if (needsFilter) { iter = Iterators.filter( iter, new Predicate<TitanElement>() { @Override public boolean apply(@Nullable TitanElement element) { return element != null && !element.isRemoved() && !isDeleted(query, element) && query.matches(element); } }); } else { iter = Iterators.filter( iter, new Predicate<TitanElement>() { @Override public boolean apply(@Nullable TitanElement element) { return element != null && !element.isRemoved() && !isDeleted(query, element); } }); } } return iter; }
@Override public Iterator<TitanRelation> execute(final VertexCentricQuery query) { if (query.getVertex().isNew()) return Iterators.emptyIterator(); final EdgeSerializer edgeSerializer = graph.getEdgeSerializer(); FittedSliceQuery sq = edgeSerializer.getQuery(query); final boolean fittedQuery = sq.isFitted(); final InternalVertex v = query.getVertex(); final boolean needsFiltering = !sq.isFitted() || !deletedRelations.isEmpty(); if (needsFiltering && sq.hasLimit()) sq = new FittedSliceQuery(sq, QueryUtil.updateLimit(sq.getLimit(), 1.1)); Iterable<TitanRelation> result = null; double limitMultiplier = 1.0; int previousDiskSize = 0; boolean finished; do { finished = true; Iterable<Entry> iter = null; if (v instanceof CacheVertex) { CacheVertex cv = (CacheVertex) v; iter = ((CacheVertex) v) .loadRelations( sq, new Retriever<SliceQuery, List<Entry>>() { @Override public List<Entry> get(SliceQuery query) { return graph.edgeQuery(v.getID(), query, txHandle); } }); } else { iter = graph.edgeQuery(v.getID(), sq, txHandle); } result = Iterables.transform( iter, new Function<Entry, TitanRelation>() { @Nullable @Override public TitanRelation apply(@Nullable Entry entry) { return edgeSerializer.readRelation(v, entry); } }); if (needsFiltering) { result = Iterables.filter( result, new Predicate<TitanRelation>() { @Override public boolean apply(@Nullable TitanRelation relation) { // Filter out updated and deleted relations return (relation == ((InternalRelation) relation).it() && !deletedRelations.containsKey(Long.valueOf(relation.getID()))) && (fittedQuery || query.matches(relation)); } }); } // Determine termination if (needsFiltering && query.hasLimit()) { if (!IterablesUtil.sizeLargerOrEqualThan(result, query.getLimit())) { int currentDiskSize = IterablesUtil.size(iter); if (currentDiskSize > previousDiskSize) { finished = false; previousDiskSize = currentDiskSize; limitMultiplier *= 2; sq = new FittedSliceQuery( sq, QueryUtil.updateLimit(sq.getLimit(), limitMultiplier)); } } } } while (!finished); return result.iterator(); }