@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<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()); }