use of org.neo4j.internal.kernel.api.PropertyIndexQuery in project neo4j by neo4j.
the class GenericNativeIndexReader method query.
@Override
public void query(QueryContext context, IndexProgressor.EntityValueClient client, IndexQueryConstraints constraints, PropertyIndexQuery... query) {
PropertyIndexQuery.GeometryRangePredicate geometryRangePredicate = getGeometryRangePredicateIfAny(query);
if (geometryRangePredicate != null) {
validateQuery(constraints, query);
try {
// If there's a GeometryRangeQuery among the predicates then this query changes from a straight-forward: build from/to and seek...
// into a query that is split into multiple sub-queries. Predicates both before and after will have to be accompanied each sub-query.
BridgingIndexProgressor multiProgressor = new BridgingIndexProgressor(client, descriptor.schema().getPropertyIds());
client.initialize(descriptor, multiProgressor, query, constraints, false);
double[] from = geometryRangePredicate.from() == null ? null : geometryRangePredicate.from().coordinate();
double[] to = geometryRangePredicate.to() == null ? null : geometryRangePredicate.to().coordinate();
CoordinateReferenceSystem crs = geometryRangePredicate.crs();
SpaceFillingCurve curve = spaceFillingCurveSettings.forCrs(crs);
List<SpaceFillingCurve.LongRange> ranges = curve.getTilesIntersectingEnvelope(from, to, configuration);
for (SpaceFillingCurve.LongRange range : ranges) {
// Here's a sub-query that we'll have to do for this geometry range. Build this query from all predicates
// and when getting to the geometry range predicate that sparked these sub-query chenanigans, swap in this sub-query in its place.
GenericKey treeKeyFrom = layout.newKey();
GenericKey treeKeyTo = layout.newKey();
initializeFromToKeys(treeKeyFrom, treeKeyTo);
boolean needFiltering = initializeRangeForGeometrySubQuery(treeKeyFrom, treeKeyTo, query, crs, range);
startSeekForInitializedRange(multiProgressor, treeKeyFrom, treeKeyTo, query, constraints, needFiltering, context.cursorContext());
}
} catch (IllegalArgumentException e) {
// Invalid query ranges will cause this state (eg. min>max)
client.initialize(descriptor, IndexProgressor.EMPTY, query, constraints, false);
}
} else {
super.query(context, client, constraints, query);
}
}
use of org.neo4j.internal.kernel.api.PropertyIndexQuery in project neo4j by neo4j.
the class QueryValidator method validateCompositeQuery.
/**
* Composite queries are somewhat restricted in what combination of predicates
* that are allowed together and in what order.
*
* 1. Decreasing precision.
* Composite queries must have decreasing precision on the slots, meaning
* for example that a range predicate can not be followed by an exact
* predicate.
* The reason for this is that because the index is sorted in lexicographic
* order with regards to the slots a predicate with increasing precision
* does not narrow down the search space in the index.
* It could of course be implemented by scanning the search space and do
* post filtering, but this is not how the implementation currently works.
*
* 2. Contains and suffix.
* Contains or suffix queries are not allowed in composite queries at all.
* This is because they both demand a full scan of the search space, just like
* "exist", and the post filtering of the result. This is how it works in the
* non-composite case but it has not yet been implemented for the composite case.
*
* @param predicates The query for which we want to check the composite validity.
*/
static void validateCompositeQuery(PropertyIndexQuery[] predicates) {
PropertyIndexQuery prev = null;
for (PropertyIndexQuery current : predicates) {
String illegalQueryMessage = "Tried to query index with illegal composite query.";
if (current instanceof PropertyIndexQuery.StringContainsPredicate || current instanceof PropertyIndexQuery.StringSuffixPredicate) {
if (predicates.length > 1) {
throw new IllegalArgumentException(format("%s Suffix or contains predicate are not allowed in composite query. Query was: %s ", illegalQueryMessage, Arrays.toString(predicates)));
}
}
if (prev instanceof PropertyIndexQuery.RangePredicate || prev instanceof PropertyIndexQuery.StringPrefixPredicate || prev instanceof PropertyIndexQuery.ExistsPredicate) {
if (!(current instanceof PropertyIndexQuery.ExistsPredicate)) {
throw new IllegalArgumentException(format("%s Composite query must have decreasing precision. Query was: %s ", illegalQueryMessage, Arrays.toString(predicates)));
}
}
prev = current;
}
}
use of org.neo4j.internal.kernel.api.PropertyIndexQuery in project neo4j by neo4j.
the class NativeIndexAccessorTests method mustHandleNestedQueries.
private void mustHandleNestedQueries(ValueIndexEntryUpdate<IndexDescriptor>[] updates) throws IndexEntryConflictException, IndexNotApplicableKernelException {
processAll(updates);
ValueCreatorUtil.sort(updates);
// when
var reader = accessor.newValueReader();
PropertyIndexQuery outerQuery = ValueCreatorUtil.rangeQuery(valueOf(updates[2]), true, valueOf(updates[3]), true);
PropertyIndexQuery innerQuery = ValueCreatorUtil.rangeQuery(valueOf(updates[0]), true, valueOf(updates[1]), true);
long[] expectedOuter = { entityIdOf(updates[2]), entityIdOf(updates[3]) };
long[] expectedInner = { entityIdOf(updates[0]), entityIdOf(updates[1]) };
Collection<Long> outerResult;
try (NodeValueIterator outerIter = query(reader, outerQuery)) {
outerResult = new ArrayList<>();
while (outerIter.hasNext()) {
outerResult.add(outerIter.next());
try (NodeValueIterator innerIter = query(reader, innerQuery)) {
assertEntityIdHits(expectedInner, innerIter);
}
}
}
assertEntityIdHits(expectedOuter, outerResult);
}
use of org.neo4j.internal.kernel.api.PropertyIndexQuery in project neo4j by neo4j.
the class FusionIndexReaderTest method mustSelectLuceneForExactPredicateWithStringValue.
@Test
void mustSelectLuceneForExactPredicateWithStringValue() throws Exception {
// given
for (Object value : FusionIndexTestHelp.valuesSupportedByLucene()) {
PropertyIndexQuery indexQuery = PropertyIndexQuery.exact(PROP_KEY, value);
// then
verifyQueryWithCorrectReader(readers.get(LUCENE), indexQuery);
}
}
Aggregations