Search in sources :

Example 6 with PropertyIndexQuery

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());
        }
    }
}
Also used : KernelTransaction(org.neo4j.kernel.api.KernelTransaction) PropertyIndexQuery(org.neo4j.internal.kernel.api.PropertyIndexQuery) TextValue(org.neo4j.values.storable.TextValue) IndexReadSession(org.neo4j.internal.kernel.api.IndexReadSession) EnumSource(org.junit.jupiter.params.provider.EnumSource) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 7 with PropertyIndexQuery

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;
}
Also used : RangePredicate(org.neo4j.internal.kernel.api.PropertyIndexQuery.RangePredicate) PropertyIndexQuery(org.neo4j.internal.kernel.api.PropertyIndexQuery) StringPrefixPredicate(org.neo4j.internal.kernel.api.PropertyIndexQuery.StringPrefixPredicate) ExactPredicate(org.neo4j.internal.kernel.api.PropertyIndexQuery.ExactPredicate)

Example 8 with PropertyIndexQuery

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);
}
Also used : Query(org.apache.lucene.search.Query) TermQuery(org.apache.lucene.search.TermQuery) BooleanQuery(org.apache.lucene.search.BooleanQuery) PropertyIndexQuery(org.neo4j.internal.kernel.api.PropertyIndexQuery)

Example 9 with PropertyIndexQuery

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));
            }
        }
    }
}
Also used : PropertyIndexQuery(org.neo4j.internal.kernel.api.PropertyIndexQuery) Value(org.neo4j.values.storable.Value) PointValue(org.neo4j.values.storable.PointValue) HeapTrackingArrayList(org.neo4j.collection.trackable.HeapTrackingArrayList) ArrayList(java.util.ArrayList)

Example 10 with PropertyIndexQuery

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);
}
Also used : KernelTransaction(org.neo4j.kernel.api.KernelTransaction) PropertyIndexQuery(org.neo4j.internal.kernel.api.PropertyIndexQuery) TokenRead(org.neo4j.internal.kernel.api.TokenRead)

Aggregations

PropertyIndexQuery (org.neo4j.internal.kernel.api.PropertyIndexQuery)24 ArrayList (java.util.ArrayList)6 KernelTransaction (org.neo4j.kernel.api.KernelTransaction)6 Value (org.neo4j.values.storable.Value)5 Test (org.junit.jupiter.api.Test)4 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)3 EnumSource (org.junit.jupiter.params.provider.EnumSource)3 Pair (org.neo4j.internal.helpers.collection.Pair)3 IndexReadSession (org.neo4j.internal.kernel.api.IndexReadSession)3 TokenRead (org.neo4j.internal.kernel.api.TokenRead)3 IndexNotApplicableKernelException (org.neo4j.internal.kernel.api.exceptions.schema.IndexNotApplicableKernelException)3 ValueIndexEntryUpdate (org.neo4j.storageengine.api.ValueIndexEntryUpdate)3 PointValue (org.neo4j.values.storable.PointValue)3 BooleanQuery (org.apache.lucene.search.BooleanQuery)2 Query (org.apache.lucene.search.Query)2 TermQuery (org.apache.lucene.search.TermQuery)2 Test (org.junit.Test)2 BridgingIndexProgressor (org.neo4j.kernel.api.index.BridgingIndexProgressor)2 SimpleEntityValueClient (org.neo4j.storageengine.api.schema.SimpleEntityValueClient)2 Duration (java.time.Duration)1