use of org.neo4j.internal.kernel.api.PropertyIndexQuery in project neo4j by neo4j.
the class CompositeIndexAccessorCompatibility method mustThrowOnIllegalCompositeQueriesAndMustNotThrowOnLegalQueries.
/* Composite query validity */
/**
* This test verify behavior for all different index patterns on a two column composite index.
* A composite query need to have decreasing precision among the queries.
* This means a range or exists query can only be followed by and exists query.
* Prefix query is also included under "range".
* Contains or suffix queries are not allowed in a composite query at all.
*
* Those are all the different combinations:
* x = exact
* < = range (also include stringPrefix)
* - = exists
* ! = stringContains or stringSuffix
* ? = any predicate
* Index patterns
* x x ok
* x < ok
* x - ok
* < x not ok
* < < not ok
* < - ok
* - x not ok
* - < not ok
* - - ok
* ! ? not ok
*/
@Test
public void mustThrowOnIllegalCompositeQueriesAndMustNotThrowOnLegalQueries() throws Exception {
Assume.assumeTrue("Assume support for granular composite queries", testSuite.supportsGranularCompositeQueries());
// given
Value someValue = Values.of(true);
TextValue someString = stringValue("");
PropertyIndexQuery firstExact = exact(100, someValue);
PropertyIndexQuery firstRange = range(100, someValue, true, someValue, true);
PropertyIndexQuery firstPrefix = stringPrefix(100, someString);
PropertyIndexQuery firstExist = exists(100);
PropertyIndexQuery firstSuffix = stringSuffix(100, someString);
PropertyIndexQuery firstContains = stringContains(100, someString);
PropertyIndexQuery secondExact = exact(200, someValue);
PropertyIndexQuery secondRange = range(200, someValue, true, someValue, true);
PropertyIndexQuery secondExist = exists(200);
PropertyIndexQuery secondPrefix = stringPrefix(100, someString);
PropertyIndexQuery secondSuffix = stringSuffix(100, someString);
PropertyIndexQuery secondContains = stringContains(100, someString);
List<Pair<PropertyIndexQuery[], Boolean>> queries = Arrays.asList(of(new PropertyIndexQuery[] { firstExact, secondExact }, true), of(new PropertyIndexQuery[] { firstExact, secondRange }, true), of(new PropertyIndexQuery[] { firstExact, secondExist }, true), of(new PropertyIndexQuery[] { firstExact, secondPrefix }, true), of(new PropertyIndexQuery[] { firstExact, secondSuffix }, false), of(new PropertyIndexQuery[] { firstExact, secondContains }, false), of(new PropertyIndexQuery[] { firstRange, secondExact }, false), of(new PropertyIndexQuery[] { firstRange, secondRange }, false), of(new PropertyIndexQuery[] { firstRange, secondExist }, true), of(new PropertyIndexQuery[] { firstRange, secondPrefix }, false), of(new PropertyIndexQuery[] { firstRange, secondSuffix }, false), of(new PropertyIndexQuery[] { firstRange, secondContains }, false), of(new PropertyIndexQuery[] { firstPrefix, secondExact }, false), of(new PropertyIndexQuery[] { firstPrefix, secondRange }, false), of(new PropertyIndexQuery[] { firstPrefix, secondExist }, true), of(new PropertyIndexQuery[] { firstPrefix, secondPrefix }, false), of(new PropertyIndexQuery[] { firstPrefix, secondSuffix }, false), of(new PropertyIndexQuery[] { firstPrefix, secondContains }, false), of(new PropertyIndexQuery[] { firstExist, secondExact }, false), of(new PropertyIndexQuery[] { firstExist, secondRange }, false), of(new PropertyIndexQuery[] { firstExist, secondExist }, true), of(new PropertyIndexQuery[] { firstExist, secondPrefix }, false), of(new PropertyIndexQuery[] { firstExist, secondSuffix }, false), of(new PropertyIndexQuery[] { firstExist, secondContains }, false), of(new PropertyIndexQuery[] { firstSuffix, secondExact }, false), of(new PropertyIndexQuery[] { firstSuffix, secondRange }, false), of(new PropertyIndexQuery[] { firstSuffix, secondExist }, false), of(new PropertyIndexQuery[] { firstSuffix, secondPrefix }, false), of(new PropertyIndexQuery[] { firstSuffix, secondSuffix }, false), of(new PropertyIndexQuery[] { firstSuffix, secondContains }, false), of(new PropertyIndexQuery[] { firstContains, secondExact }, false), of(new PropertyIndexQuery[] { firstContains, secondRange }, false), of(new PropertyIndexQuery[] { firstContains, secondExist }, false), of(new PropertyIndexQuery[] { firstContains, secondPrefix }, false), of(new PropertyIndexQuery[] { firstContains, secondSuffix }, false), of(new PropertyIndexQuery[] { firstContains, secondContains }, false));
SimpleEntityValueClient client = new SimpleEntityValueClient();
try (ValueIndexReader reader = accessor.newValueReader()) {
for (Pair<PropertyIndexQuery[], Boolean> pair : queries) {
PropertyIndexQuery[] theQuery = pair.first();
Boolean legal = pair.other();
if (legal) {
// when
reader.query(NULL_CONTEXT, client, unconstrained(), theQuery);
// then should not throw
} else {
try {
// when
reader.query(NULL_CONTEXT, client, unconstrained(), theQuery);
fail("Expected index reader to throw for illegal composite query. Query was, " + Arrays.toString(theQuery));
} catch (IllegalArgumentException e) {
// then
assertThat(e.getMessage()).contains("Tried to query index with illegal composite query.");
}
}
}
}
}
use of org.neo4j.internal.kernel.api.PropertyIndexQuery in project neo4j by neo4j.
the class IndexOrderTestBase method shouldRangeScanInOrderWithTxState.
@ParameterizedTest
@EnumSource(value = IndexOrder.class, names = { "ASCENDING", "DESCENDING" })
void shouldRangeScanInOrderWithTxState(IndexOrder indexOrder) throws Exception {
List<Pair<Long, Value>> expected = new ArrayList<>();
try (KernelTransaction tx = beginTransaction()) {
expected.add(entityWithProp(tx, "hello"));
entityWithProp(tx, "bellow");
expected.add(entityWithProp(tx, "schmello"));
expected.add(entityWithProp(tx, "low"));
expected.add(entityWithProp(tx, "trello"));
entityWithProp(tx, "yellow");
expected.add(entityWithProp(tx, "loww"));
entityWithProp(tx, "below");
tx.commit();
}
createIndex();
// when
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)) {
entityWithProp(tx, "allow");
expected.add(entityWithProp(tx, "now"));
expected.add(entityWithProp(tx, "jello"));
entityWithProp(tx, "willow");
PropertyIndexQuery query = PropertyIndexQuery.range(prop, "hello", true, "trello", true);
entityIndexSeek(tx, index, cursor, constrained(indexOrder, true), query);
assertResultsInOrder(expected, cursor, indexOrder);
}
}
}
use of org.neo4j.internal.kernel.api.PropertyIndexQuery in project neo4j by neo4j.
the class IndexOrderTestBase method shouldPrefixScanInOrder.
@ParameterizedTest
@EnumSource(value = IndexOrder.class, names = { "ASCENDING", "DESCENDING" })
void shouldPrefixScanInOrder(IndexOrder indexOrder) throws Exception {
List<Pair<Long, Value>> expected = new ArrayList<>();
try (KernelTransaction tx = beginTransaction()) {
expected.add(entityWithProp(tx, "bee hive"));
entityWithProp(tx, "a");
expected.add(entityWithProp(tx, "become"));
expected.add(entityWithProp(tx, "be"));
expected.add(entityWithProp(tx, "bachelor"));
entityWithProp(tx, "street smart");
expected.add(entityWithProp(tx, "builder"));
entityWithProp(tx, "ceasar");
tx.commit();
}
createIndex();
// when
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)) {
entityWithProp(tx, "allow");
expected.add(entityWithProp(tx, "bastard"));
expected.add(entityWithProp(tx, "bully"));
entityWithProp(tx, "willow");
PropertyIndexQuery query = PropertyIndexQuery.stringPrefix(prop, stringValue("b"));
entityIndexSeek(tx, index, cursor, constrained(indexOrder, true), query);
assertResultsInOrder(expected, cursor, indexOrder);
}
}
}
use of org.neo4j.internal.kernel.api.PropertyIndexQuery in project neo4j by neo4j.
the class SchemaComplianceChecker method verifyIndexedUniquely.
private <ENTITY extends PrimitiveRecord> void verifyIndexedUniquely(ENTITY entity, Value[] propertyValues, IndexDescriptor indexRule, ValueIndexReader reader, Function<ENTITY, ConsistencyReport.PrimitiveConsistencyReport> reportSupplier) {
long nodeId = entity.getId();
PropertyIndexQuery[] query = seek(indexRule.schema(), propertyValues);
LongIterator indexedNodeIds = queryIndexOrEmpty(reader, query);
long count = 0;
while (indexedNodeIds.hasNext()) {
long indexedNodeId = indexedNodeIds.next();
if (nodeId == indexedNodeId) {
count++;
} else {
reportSupplier.apply(entity).uniqueIndexNotUnique(indexRule, Values.asObjects(propertyValues), indexedNodeId);
}
}
reportIncorrectIndexCount(entity, propertyValues, indexRule, count, reportSupplier);
}
use of org.neo4j.internal.kernel.api.PropertyIndexQuery in project neo4j by neo4j.
the class FulltextIndexReader method query.
@Override
public void query(QueryContext context, IndexProgressor.EntityValueClient client, IndexQueryConstraints constraints, PropertyIndexQuery... queries) throws IndexNotApplicableKernelException {
BooleanQuery.Builder queryBuilder = new BooleanQuery.Builder();
for (PropertyIndexQuery indexQuery : queries) {
if (indexQuery.type() == PropertyIndexQuery.IndexQueryType.fulltextSearch) {
PropertyIndexQuery.FulltextSearchPredicate fulltextSearch = (PropertyIndexQuery.FulltextSearchPredicate) indexQuery;
try {
queryBuilder.add(parseFulltextQuery(fulltextSearch.query()), BooleanClause.Occur.SHOULD);
} catch (ParseException e) {
throw new RuntimeException("Could not parse the given fulltext search query: '" + fulltextSearch.query() + "'.", e);
}
} else {
// Not fulltext query
assertNotComposite(queries);
assertCypherCompatible();
Query query;
if (indexQuery.type() == PropertyIndexQuery.IndexQueryType.stringContains) {
PropertyIndexQuery.StringContainsPredicate scp = (PropertyIndexQuery.StringContainsPredicate) indexQuery;
String searchTerm = QueryParser.escape(scp.contains().stringValue());
Term term = new Term(propertyNames[0], "*" + searchTerm + "*");
query = new WildcardQuery(term);
} else if (indexQuery.type() == PropertyIndexQuery.IndexQueryType.stringSuffix) {
PropertyIndexQuery.StringSuffixPredicate ssp = (PropertyIndexQuery.StringSuffixPredicate) indexQuery;
String searchTerm = QueryParser.escape(ssp.suffix().stringValue());
Term term = new Term(propertyNames[0], "*" + searchTerm);
query = new WildcardQuery(term);
} else if (indexQuery.type() == PropertyIndexQuery.IndexQueryType.stringPrefix) {
PropertyIndexQuery.StringPrefixPredicate spp = (PropertyIndexQuery.StringPrefixPredicate) indexQuery;
String searchTerm = spp.prefix().stringValue();
Term term = new Term(propertyNames[0], searchTerm);
query = new LuceneDocumentStructure.PrefixMultiTermsQuery(term);
} else if (indexQuery.getClass() == PropertyIndexQuery.ExactPredicate.class && indexQuery.valueGroup() == ValueGroup.TEXT) {
PropertyIndexQuery.ExactPredicate exact = (PropertyIndexQuery.ExactPredicate) indexQuery;
String searchTerm = ((TextValue) exact.value()).stringValue();
Term term = new Term(propertyNames[0], searchTerm);
query = new ConstantScoreQuery(new TermQuery(term));
} else if (indexQuery.getClass() == PropertyIndexQuery.TextRangePredicate.class) {
PropertyIndexQuery.TextRangePredicate sp = (PropertyIndexQuery.TextRangePredicate) indexQuery;
query = newRangeSeekByStringQuery(propertyNames[0], sp.from(), sp.fromInclusive(), sp.to(), sp.toInclusive());
} else {
throw new IndexNotApplicableKernelException("A fulltext schema index cannot answer " + indexQuery.type() + " queries on " + indexQuery.valueCategory() + " values.");
}
queryBuilder.add(query, BooleanClause.Occur.MUST);
}
}
Query query = queryBuilder.build();
ValuesIterator itr = searchLucene(query, constraints, context, context.cursorContext(), context.memoryTracker());
IndexProgressor progressor = new FulltextIndexProgressor(itr, client, constraints);
client.initialize(index, progressor, queries, constraints, true);
}
Aggregations