use of org.neo4j.internal.kernel.api.PropertyIndexQuery in project neo4j by neo4j.
the class IndexOrderTestBase method shouldNodeIndexScanInOrderWithStringInMemoryAndConcurrentUpdate.
@ParameterizedTest
@EnumSource(value = IndexOrder.class, names = { "ASCENDING", "DESCENDING" })
void shouldNodeIndexScanInOrderWithStringInMemoryAndConcurrentUpdate(IndexOrder indexOrder) throws Exception {
String a = "a";
String b = "b";
String c = "c";
createIndex();
TextValue expectedFirst = indexOrder == IndexOrder.ASCENDING ? stringValue(a) : stringValue(c);
TextValue expectedLast = indexOrder == IndexOrder.ASCENDING ? stringValue(c) : stringValue(a);
try (KernelTransaction tx = beginTransaction()) {
int prop = tx.tokenRead().propertyKey(DEFAULT_PROPERTY_NAME);
entityWithProp(tx, a);
entityWithProp(tx, c);
IndexReadSession index = tx.dataRead().indexReadSession(tx.schemaRead().indexGetForName(INDEX_NAME));
try (var cursor = getEntityValueIndexCursor(tx)) {
PropertyIndexQuery query = PropertyIndexQuery.stringPrefix(prop, stringValue(""));
entityIndexSeek(tx, index, cursor, constrained(indexOrder, true), query);
assertTrue(cursor.next());
assertThat(cursor.propertyValue(0)).isEqualTo(expectedFirst);
assertTrue(cursor.next());
assertThat(cursor.propertyValue(0)).isEqualTo(expectedLast);
concurrentInsert(b);
assertFalse(cursor.next(), () -> "Did not expect to find anything more but found " + cursor.propertyValue(0));
}
tx.commit();
}
// Verify we see all data in the end
try (KernelTransaction tx = beginTransaction()) {
int prop = tx.tokenRead().propertyKey(DEFAULT_PROPERTY_NAME);
IndexReadSession index = tx.dataRead().indexReadSession(tx.schemaRead().indexGetForName(INDEX_NAME));
try (var cursor = getEntityValueIndexCursor(tx)) {
PropertyIndexQuery query = PropertyIndexQuery.stringPrefix(prop, stringValue(""));
entityIndexSeek(tx, index, cursor, constrained(indexOrder, true), query);
assertTrue(cursor.next());
assertThat(cursor.propertyValue(0)).isEqualTo(expectedFirst);
assertTrue(cursor.next());
assertThat(cursor.propertyValue(0)).isEqualTo(stringValue(b));
assertTrue(cursor.next());
assertThat(cursor.propertyValue(0)).isEqualTo(expectedLast);
assertFalse(cursor.next());
}
}
}
use of org.neo4j.internal.kernel.api.PropertyIndexQuery in project neo4j by neo4j.
the class GenericNativeIndexReader method initializeRangeForGeometrySubQuery.
/**
* Initializes {@code treeKeyFrom} and {@code treeKeyTo} from the {@link PropertyIndexQuery query}.
* Geometry range queries makes an otherwise straight-forward key construction complex in that a geometry range internally is performed
* by executing multiple sub-range queries to the index. Each of those sub-range queries still needs to construct the full composite key -
* in the case of a composite index. Therefore this method can be called either with null or non-null {@code crs} and {@code range} and
* constructing a key when coming across a {@link PropertyIndexQuery.GeometryRangePredicate} will use the provided crs/range instead
* of the predicate, where the specific range is one out of many sub-ranges calculated from the {@link PropertyIndexQuery.GeometryRangePredicate}
* by the caller.
*
* @param treeKeyFrom the "from" key to construct from the query.
* @param treeKeyTo the "to" key to construct from the query.
* @param query the query to construct keys from to later send to {@link GBPTree} when reading.
* @param crs {@link CoordinateReferenceSystem} for the specific {@code range}, if range is specified too.
* @param range sub-range of a larger {@link PropertyIndexQuery.GeometryRangePredicate} to use instead of {@link PropertyIndexQuery.GeometryRangePredicate}
* in the query.
* @return {@code true} if filtering is needed for the results from the reader, otherwise {@code false}.
*/
private static boolean initializeRangeForGeometrySubQuery(GenericKey treeKeyFrom, GenericKey treeKeyTo, PropertyIndexQuery[] query, CoordinateReferenceSystem crs, SpaceFillingCurve.LongRange range) {
boolean needsFiltering = false;
for (int i = 0; i < query.length; i++) {
PropertyIndexQuery predicate = query[i];
switch(predicate.type()) {
case exists:
treeKeyFrom.initValueAsLowest(i, ValueGroup.UNKNOWN);
treeKeyTo.initValueAsHighest(i, ValueGroup.UNKNOWN);
break;
case exact:
ExactPredicate exactPredicate = (ExactPredicate) predicate;
treeKeyFrom.initFromValue(i, exactPredicate.value(), NEUTRAL);
treeKeyTo.initFromValue(i, exactPredicate.value(), NEUTRAL);
break;
case range:
if (isGeometryRangeQuery(predicate)) {
// Use the supplied SpaceFillingCurve range instead of the GeometryRangePredicate because at the time of calling this method
// the original geometry range have been split up into multiple sub-ranges and this invocation is for one of those sub-ranges.
// We can not take query inclusion / exclusion into consideration here because then we risk missing border values. Always use
// Inclusion.LOW / HIGH respectively and filter out points later on.
treeKeyFrom.stateSlot(i).writePointDerived(crs, range.min, LOW);
treeKeyTo.stateSlot(i).writePointDerived(crs, range.max + 1, HIGH);
needsFiltering = true;
} else {
RangePredicate<?> rangePredicate = (RangePredicate<?>) predicate;
initFromForRange(i, rangePredicate, treeKeyFrom);
initToForRange(i, rangePredicate, treeKeyTo);
}
break;
case stringPrefix:
StringPrefixPredicate prefixPredicate = (StringPrefixPredicate) predicate;
treeKeyFrom.stateSlot(i).initAsPrefixLow(prefixPredicate.prefix());
treeKeyTo.stateSlot(i).initAsPrefixHigh(prefixPredicate.prefix());
break;
case stringSuffix:
case stringContains:
treeKeyFrom.initValueAsLowest(i, ValueGroup.TEXT);
treeKeyTo.initValueAsHighest(i, ValueGroup.TEXT);
needsFiltering = true;
break;
default:
throw new IllegalArgumentException("IndexQuery of type " + predicate.type() + " is not supported.");
}
}
return needsFiltering;
}
use of org.neo4j.internal.kernel.api.PropertyIndexQuery in project neo4j by neo4j.
the class SimpleValueIndexReader method query.
@Override
public void query(QueryContext context, IndexProgressor.EntityValueClient client, IndexQueryConstraints constraints, PropertyIndexQuery... predicates) throws IndexNotApplicableKernelException {
Query query = toLuceneQuery(predicates);
client.initialize(descriptor, search(query).getIndexProgressor(NODE_ID_KEY, client), predicates, constraints, false);
}
use of org.neo4j.internal.kernel.api.PropertyIndexQuery in project neo4j by neo4j.
the class DefaultEntityValueIndexCursor method initialize.
@Override
public final void initialize(IndexDescriptor descriptor, IndexProgressor progressor, PropertyIndexQuery[] query, IndexQueryConstraints constraints, boolean indexIncludesTransactionState) {
assert query != null;
super.initialize(progressor);
this.indexOrder = constraints.order();
this.needsValues = constraints.needsValues();
sortedMergeJoin.initialize(indexOrder);
this.query = query;
if (tracer != null) {
tracer.onIndexSeek();
}
shortcutSecurity = setupSecurity(descriptor);
if (!indexIncludesTransactionState && read.hasTxStateWithChanges() && query.length > 0) {
// Extract out the equality queries
List<Value> exactQueryValues = new ArrayList<>(query.length);
int i = 0;
while (i < query.length && query[i] instanceof PropertyIndexQuery.ExactPredicate) {
exactQueryValues.add(((PropertyIndexQuery.ExactPredicate) query[i]).value());
i++;
}
Value[] exactValues = exactQueryValues.toArray(new Value[0]);
if (i == query.length) {
// Only exact queries
// No need to order, all values are the same
this.indexOrder = IndexOrder.NONE;
seekQuery(descriptor, exactValues);
} else {
PropertyIndexQuery nextQuery = query[i];
switch(nextQuery.type()) {
case exists:
// This also covers the rewritten suffix/contains for composite index
// If composite index all following will be exists as well so no need to consider those
setNeedsValuesIfRequiresOrder();
if (exactQueryValues.isEmpty()) {
// First query is exists, use scan
scanQuery(descriptor);
} else {
rangeQuery(descriptor, exactValues, null);
}
break;
case range:
// This case covers first query to be range or exact followed by range
// If composite index all following will be exists as well so no need to consider those
setNeedsValuesIfRequiresOrder();
rangeQuery(descriptor, exactValues, (PropertyIndexQuery.RangePredicate<?>) nextQuery);
break;
case stringPrefix:
// This case covers first query to be prefix or exact followed by prefix
// If composite index all following will be exists as well so no need to consider those
setNeedsValuesIfRequiresOrder();
prefixQuery(descriptor, exactValues, (PropertyIndexQuery.StringPrefixPredicate) nextQuery);
break;
case stringSuffix:
case stringContains:
// have been rewritten as exists + filter, so no need to consider it here
assert query.length == 1;
suffixOrContainsQuery(descriptor, nextQuery);
break;
default:
throw new UnsupportedOperationException("Query not supported: " + Arrays.toString(query));
}
}
}
}
use of org.neo4j.internal.kernel.api.PropertyIndexQuery in project neo4j by neo4j.
the class TransactionImpl method findRelationships.
@Override
public ResourceIterator<Relationship> findRelationships(RelationshipType relationshipType, String key, String template, StringSearchMode searchMode) {
checkRelationshipType(relationshipType);
checkPropertyKey(key);
checkArgument(template != null, "Template must not be null");
KernelTransaction transaction = kernelTransaction();
TokenRead tokenRead = transaction.tokenRead();
int typeId = tokenRead.relationshipType(relationshipType.name());
int propertyId = tokenRead.propertyKey(key);
PropertyIndexQuery query = getIndexQuery(template, searchMode, propertyId);
return relationshipsByTypeAndProperty(transaction, typeId, query);
}
Aggregations