public static final Condition<TitanElement> indexCover(final MixedIndexType index, Condition<TitanElement> condition, final IndexSerializer indexInfo, final Set<Condition> covered) { assert QueryUtil.isQueryNormalForm(condition); assert condition instanceof And; And<TitanElement> subcondition = new And<TitanElement>(condition.numChildren()); for (Condition<TitanElement> subclause : condition.getChildren()) { if (coversAll(index,subclause,indexInfo)) { subcondition.add(subclause); covered.add(subclause); } } return subcondition.isEmpty()?null:subcondition; }
return (key + ":(" + escapeValue(terms.get(0)) + ")"); } else { And<TitanElement> andTerms = new And<TitanElement>(); for (String term : terms) { andTerms.add(new PredicateCondition<String, TitanElement>(key, titanPredicate, term)); else return ""; } else if (condition instanceof And) { int numChildren = ((And) condition).size(); StringBuilder sb = new StringBuilder(); for (Condition<TitanElement> c : condition.getChildren()) {
query = new BackendQueryHolder<JointIndexQuery>(jointQuery, coveredClauses.size()==conditions.numChildren(), isSorted); } else { query = new BackendQueryHolder<JointIndexQuery>(new JointIndexQuery(), false, isSorted);
/** * Constructs a {@link VertexCentricQuery} for this query builder. The query construction and optimization * logic is taken from {@link #constructQuery(com.thinkaurelius.titan.graphdb.internal.RelationCategory)} * This method only adds the additional conditions that are based on the base vertex. * * @param vertex for which to construct this query * @param baseQuery as constructed by {@link #constructQuery(com.thinkaurelius.titan.graphdb.internal.RelationCategory)} * @return */ protected VertexCentricQuery constructQuery(InternalVertex vertex, BaseVertexCentricQuery baseQuery) { Condition<TitanRelation> condition = baseQuery.getCondition(); if (!baseQuery.isEmpty()) { //Add adjacent-vertex and direction related conditions; copy conditions to so that baseQuery does not change And<TitanRelation> newcond = new And<TitanRelation>(); if (condition instanceof And) newcond.addAll((And) condition); else newcond.add(condition); newcond.add(new DirectionCondition<TitanRelation>(vertex,dir)); if (adjacentVertex != null) newcond.add(new IncidenceCondition<TitanRelation>(vertex,adjacentVertex)); condition = newcond; } VertexCentricQuery query = new VertexCentricQuery(vertex, condition, baseQuery.getDirection(), baseQuery.getQueries(),baseQuery.getOrders(), baseQuery.getLimit()); Preconditions.checkArgument(!queryOnlyLoaded || query.isSimple(),"Query-only-loaded only works on simple queries"); return query; }
public static final<E extends TitanElement> Condition<E> transformation(Condition<E> condition, Function<Condition<E>,Condition<E>> transformation) { Condition<E> transformed = transformation.apply(condition); if (transformed!=null) return transformed; //if transformed==null we go a level deeper if (condition.getType()== Condition.Type.LITERAL) { return condition; } else if (condition instanceof Not) { return Not.of(transformation(((Not) condition).getChild(), transformation)); } else if (condition instanceof And) { And<E> newand = new And<E>(condition.numChildren()); for (Condition<E> child : condition.getChildren()) newand.add(transformation(child, transformation)); return newand; } else if (condition instanceof Or) { Or<E> newor = new Or<E>(condition.numChildren()); for (Condition<E> child : condition.getChildren()) newor.add(transformation(child, transformation)); return newor; } else throw new IllegalArgumentException("Unexpected condition type: " + condition); }
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) { sliceLimit *= 2; query.getBackendQuery().setLimit(computeLimit(conditions.size(),sliceLimit)); queries = ImmutableList.of(query); conditions.add(returnType); conditions.add(new VisibilityFilterCondition<TitanRelation>( //Need this to filter out newly created invisible relations in the transaction 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 return BaseVertexCentricQuery.emptyQuery(); conditions.add(getTypeCondition(ts));
@Override public And<E> clone() { return new And<E>(this); }
@Test public void testTTL() throws Exception { if (!index.getFeatures().supportsDocumentTTL()) return; final String store = "store1"; initialize(store); // add couple of documents with weight > 4.0d add(store, "expiring-doc1", ImmutableMultimap.of(NAME, "first", TIME, 1L, WEIGHT, 10.2d), true, 2); add(store, "expiring-doc2", ImmutableMultimap.of(NAME, "second", TIME, 2L, WEIGHT, 4.7d), true); add(store, "expiring-doc3", ImmutableMultimap.of(NAME, "third", TIME, 3L, WEIGHT, 5.2d), true, 2); add(store, "expiring-doc4", ImmutableMultimap.of(NAME, "fourth", TIME, 3L, WEIGHT, 7.7d), true, 7);// bigger ttl then one recycle interval, should still show up in the results clopen(); // initial query Set<String> results = Sets.newHashSet(tx.query(new IndexQuery(store, And.of(PredicateCondition.of(WEIGHT, Cmp.GREATER_THAN_EQUAL, 4.0))))); assertEquals(4, results.size()); Thread.sleep(6000); // sleep for elastic search ttl recycle results = Sets.newHashSet(tx.query(new IndexQuery(store, And.of(PredicateCondition.of(WEIGHT, Cmp.GREATER_THAN_EQUAL, 4.0))))); assertEquals(2, results.size()); assertTrue(results.contains("expiring-doc2")); assertTrue(results.contains("expiring-doc4")); Thread.sleep(5000); // sleep for elastic search ttl recycle results = Sets.newHashSet(tx.query(new IndexQuery(store, And.of(PredicateCondition.of(WEIGHT, Cmp.GREATER_THAN_EQUAL, 4.0))))); assertEquals(1, results.size()); assertTrue(results.contains("expiring-doc2")); }
private PredicateCondition<PropertyKey, TitanElement> getEqualityCondition(Condition<TitanElement> condition) { if (condition instanceof PredicateCondition) { PredicateCondition<PropertyKey, TitanElement> pc = (PredicateCondition) condition; if (pc.getPredicate() == Cmp.EQUAL && TypeUtil.hasSimpleInternalVertexKeyIndex(pc.getKey())) return pc; } else if (condition instanceof And) { for (Condition<TitanElement> child : ((And<TitanElement>) condition).getChildren()) { PredicateCondition<PropertyKey, TitanElement> p = getEqualityCondition(child); if (p != null) return p; } } return null; }
public static final <E extends TitanElement> Condition<E> simplifyQNF(Condition<E> condition) { Preconditions.checkArgument(isQueryNormalForm(condition)); if (condition.numChildren() == 1) { Condition<E> child = ((And) condition).get(0); if (child.getType() == Condition.Type.LITERAL) return child; } return condition; }
/** * Constructs a {@link VertexCentricQuery} for this query builder. The query construction and optimization * logic is taken from {@link #constructQuery(com.thinkaurelius.titan.graphdb.internal.RelationCategory)} * This method only adds the additional conditions that are based on the base vertex. * * @param vertex for which to construct this query * @param baseQuery as constructed by {@link #constructQuery(com.thinkaurelius.titan.graphdb.internal.RelationCategory)} * @return */ protected VertexCentricQuery constructQuery(InternalVertex vertex, BaseVertexCentricQuery baseQuery) { Condition<TitanRelation> condition = baseQuery.getCondition(); if (!baseQuery.isEmpty()) { //Add adjacent-vertex and direction related conditions; copy conditions to so that baseQuery does not change And<TitanRelation> newcond = new And<TitanRelation>(); if (condition instanceof And) newcond.addAll((And) condition); else newcond.add(condition); newcond.add(new DirectionCondition<TitanRelation>(vertex,dir)); if (adjacentVertex != null) newcond.add(new IncidenceCondition<TitanRelation>(vertex,adjacentVertex)); condition = newcond; } VertexCentricQuery query = new VertexCentricQuery(vertex, condition, baseQuery.getDirection(), baseQuery.getQueries(),baseQuery.getOrders(), baseQuery.getLimit()); Preconditions.checkArgument(!queryOnlyLoaded || query.isSimple(),"Query-only-loaded only works on simple queries"); return query; }
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) { sliceLimit *= 2; query.getBackendQuery().setLimit(computeLimit(conditions.size(),sliceLimit)); queries = ImmutableList.of(query); conditions.add(returnType); conditions.add(new VisibilityFilterCondition<TitanRelation>( //Need this to filter out newly created invisible relations in the transaction 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 return BaseVertexCentricQuery.emptyQuery(); conditions.add(getTypeCondition(ts));
public static <E extends TitanElement> And<E> of(Condition<E>... elements) { return new And<E>(elements); }
@Test public void largeTest() throws Exception { int numDoc = 30000; String store = "vertex"; initialize(store); for (int i = 1; i <= numDoc; i++) { add(store, "doc" + i, getRandomDocument(), true); } clopen(); // List<String> result = tx.query(new IndexQuery(store, And.of(PredicateCondition.of(WEIGHT, Cmp.INTERVAL, Interval.of(0.2,0.3))))); // List<String> result = tx.query(new IndexQuery(store, And.of(PredicateCondition.of(LOCATION, Geo.WITHIN,Geoshape.circle(48.5,0.5,1000.00))))); long time = System.currentTimeMillis(); List<String> result = tx.query(new IndexQuery(store, And.of(PredicateCondition.of(WEIGHT, Cmp.GREATER_THAN_EQUAL, 0.2), PredicateCondition.of(WEIGHT, Cmp.LESS_THAN, 0.6), PredicateCondition.of(LOCATION, Geo.WITHIN, Geoshape.circle(48.5, 0.5, 1000.00))))); int oldresultSize = result.size(); System.out.println(result.size() + " vs " + (numDoc / 1000 * 2.4622623015)); System.out.println("Query time on " + numDoc + " docs (ms): " + (System.currentTimeMillis() - time)); result = tx.query(new IndexQuery(store, And.of(PredicateCondition.of(WEIGHT, Cmp.GREATER_THAN_EQUAL, 0.2), PredicateCondition.of(WEIGHT, Cmp.LESS_THAN, 0.6), PredicateCondition.of(LOCATION, Geo.WITHIN, Geoshape.circle(48.5, 0.5, 1000.00))), numDoc / 1000)); assertEquals(numDoc / 1000, result.size()); result = tx.query(new IndexQuery(store, And.of(PredicateCondition.of(WEIGHT, Cmp.GREATER_THAN_EQUAL, 0.2), PredicateCondition.of(WEIGHT, Cmp.LESS_THAN, 0.6), PredicateCondition.of(LOCATION, Geo.WITHIN, Geoshape.circle(48.5, 0.5, 1000.00))), numDoc / 1000 * 100)); assertEquals(oldresultSize, result.size()); }
/** * Query-normal-form (QNF) for Titan is a variant of CNF (conjunctive normal form) with negation inlined where possible * * @param condition * @return */ public static boolean isQueryNormalForm(Condition<?> condition) { if (isQNFLiteralOrNot(condition)) return true; else if (condition instanceof And) { for (Condition<?> child : ((And<?>) condition).getChildren()) { if (isQNFLiteralOrNot(child)) continue; else if (child instanceof Or) { for (Condition<?> child2 : ((Or<?>) child).getChildren()) { if (!isQNFLiteralOrNot(child2)) return false; } } else return false; } return true; } else return false; }
public static final <E extends TitanElement> Condition<E> simplifyQNF(Condition<E> condition) { Preconditions.checkArgument(isQueryNormalForm(condition)); if (condition.numChildren() == 1) { Condition<E> child = ((And) condition).get(0); if (child.getType() == Condition.Type.LITERAL) return child; } return condition; }
public static final Condition<TitanElement> indexCover(final MixedIndexType index, Condition<TitanElement> condition, final IndexSerializer indexInfo, final Set<Condition> covered) { assert QueryUtil.isQueryNormalForm(condition); assert condition instanceof And; And<TitanElement> subcondition = new And<TitanElement>(condition.numChildren()); for (Condition<TitanElement> subclause : condition.getChildren()) { if (coversAll(index,subclause,indexInfo)) { subcondition.add(subclause); covered.add(subclause); } } return subcondition.isEmpty()?null:subcondition; }
return (key + ":(" + escapeValue(terms.get(0)) + ")"); } else { And<TitanElement> andTerms = new And<>(); for (String term : terms) { andTerms.add(new PredicateCondition<>(key, titanPredicate, term)); else return ""; } else if (condition instanceof And) { int numChildren = ((And) condition).size(); StringBuilder sb = new StringBuilder(); for (Condition<TitanElement> c : condition.getChildren()) {
public static final<E extends TitanElement> Condition<E> transformation(Condition<E> condition, Function<Condition<E>,Condition<E>> transformation) { Condition<E> transformed = transformation.apply(condition); if (transformed!=null) return transformed; //if transformed==null we go a level deeper if (condition.getType()== Condition.Type.LITERAL) { return condition; } else if (condition instanceof Not) { return Not.of(transformation(((Not) condition).getChild(), transformation)); } else if (condition instanceof And) { And<E> newand = new And<E>(condition.numChildren()); for (Condition<E> child : condition.getChildren()) newand.add(transformation(child, transformation)); return newand; } else if (condition instanceof Or) { Or<E> newor = new Or<E>(condition.numChildren()); for (Condition<E> child : condition.getChildren()) newor.add(transformation(child, transformation)); return newor; } else throw new IllegalArgumentException("Unexpected condition type: " + condition); }