use of org.neo4j.kernel.impl.index.schema.NodeValueIterator in project neo4j by neo4j.
the class DatabaseIndexAccessorTest method results.
private static NodeValueIterator results(ValueIndexReader reader, PropertyIndexQuery... queries) throws IndexNotApplicableKernelException {
NodeValueIterator results = new NodeValueIterator();
reader.query(NULL_CONTEXT, results, unconstrained(), queries);
return results;
}
use of org.neo4j.kernel.impl.index.schema.NodeValueIterator in project neo4j by neo4j.
the class LuceneSchemaIndexPopulationIT method partitionedIndexPopulation.
@ParameterizedTest
@ValueSource(ints = { 7, 11, 14, 20, 35, 58 })
void partitionedIndexPopulation(int affectedNodes) throws Exception {
Path rootFolder = testDir.directory("partitionIndex" + affectedNodes).resolve("uniqueIndex" + affectedNodes);
try (SchemaIndex uniqueIndex = LuceneSchemaIndexBuilder.create(descriptor, writable(), Config.defaults()).withFileSystem(fileSystem).withIndexRootFolder(rootFolder).build()) {
uniqueIndex.open();
// index is empty and not yet exist
assertEquals(0, uniqueIndex.allDocumentsReader().maxCount());
assertFalse(uniqueIndex.exists());
try (LuceneIndexAccessor indexAccessor = new LuceneIndexAccessor(uniqueIndex, descriptor, SIMPLE_TOKEN_LOOKUP)) {
generateUpdates(indexAccessor, affectedNodes);
indexAccessor.force(NULL);
// now index is online and should contain updates data
assertTrue(uniqueIndex.isOnline());
try (var indexReader = indexAccessor.newValueReader();
NodeValueIterator results = new NodeValueIterator();
IndexSampler indexSampler = indexReader.createSampler()) {
indexReader.query(NULL_CONTEXT, results, unconstrained(), PropertyIndexQuery.exists(1));
long[] nodes = PrimitiveLongCollections.asArray(results);
assertEquals(affectedNodes, nodes.length);
IndexSample sample = indexSampler.sampleIndex(NULL);
assertEquals(affectedNodes, sample.indexSize());
assertEquals(affectedNodes, sample.uniqueValues());
assertEquals(affectedNodes, sample.sampleSize());
}
}
}
}
use of org.neo4j.kernel.impl.index.schema.NodeValueIterator in project neo4j by neo4j.
the class SimpleIndexPopulatorCompatibility method shouldPopulateAndUpdate.
@Test
public void shouldPopulateAndUpdate() throws Exception {
// GIVEN
withPopulator(indexProvider.getPopulator(descriptor, indexSamplingConfig, heapBufferFactory(1024), INSTANCE, tokenNameLookup), p -> p.add(updates(valueSet1), NULL));
try (IndexAccessor accessor = indexProvider.getOnlineAccessor(descriptor, indexSamplingConfig, tokenNameLookup)) {
// WHEN
try (IndexUpdater updater = accessor.newUpdater(IndexUpdateMode.ONLINE, NULL)) {
List<ValueIndexEntryUpdate<?>> updates = updates(valueSet2);
for (ValueIndexEntryUpdate<?> update : updates) {
updater.process(update);
}
}
// THEN
try (ValueIndexReader reader = accessor.newValueReader()) {
int propertyKeyId = descriptor.schema().getPropertyId();
for (NodeAndValue entry : Iterables.concat(valueSet1, valueSet2)) {
try (NodeValueIterator nodes = new NodeValueIterator()) {
reader.query(NULL_CONTEXT, nodes, unconstrained(), PropertyIndexQuery.exact(propertyKeyId, entry.value));
assertEquals(entry.nodeId, nodes.next());
assertFalse(nodes.hasNext());
}
}
}
}
}
use of org.neo4j.kernel.impl.index.schema.NodeValueIterator in project neo4j by neo4j.
the class SimpleIndexPopulatorCompatibility method shouldPopulateAndRemoveEntriesWithSimilarMinimalSplitter.
/**
* This test target a bug around minimal splitter in gbpTree and unique index populator. It goes like this:
* Given a set of updates (value,entityId):
* - ("A01",1), ("A90",3), ("A9",2)
* If ("A01",1) and ("A90",3) would cause a split to occur they would produce a minimal splitter ("A9",3).
* Note that the value in this minimal splitter is equal to our last update ("A9",2).
* When making insertions with the unique populator we don't compare entityId which would means ("A9",2)
* ends up to the right of ("A9",3), even though it belongs to the left because of entityId being smaller.
* At this point the tree is in an inconsistent (key on wrong side of splitter).
*
* To work around this problem the entityId is only kept in minimal splitter if strictly necessary to divide
* left from right. This means the minimal splitter between ("A01",1) and ("A90",3) is ("A9",-1) and ("A9",2)
* will correctly be placed on the right side of this splitter.
*
* To trigger this scenario this test first insert a bunch of values that are all unique and that will cause a
* split to happen. This is the firstBatch.
* The second batch are constructed so that at least one of them will have a value equal to the splitter key
* constructed during the firstBatch.
* It's important that the secondBatch has ids that are lower than the first batch to align with example described above.
*/
@Test
public void shouldPopulateAndRemoveEntriesWithSimilarMinimalSplitter() throws Exception {
String prefix = "Work out your own salvation. Do not depend on others. ";
int nbrOfNodes = 200;
long nodeId = 0;
// Second batch has lower ids
List<NodeAndValue> secondBatch = new ArrayList<>();
for (int i = 0; i < nbrOfNodes; i++) {
secondBatch.add(new NodeAndValue(nodeId++, stringValue(prefix + i)));
}
// First batch has higher ids and minimal splitter among values in first batch will be found among second batch
List<NodeAndValue> firstBatch = new ArrayList<>();
for (int i = 0; i < nbrOfNodes; i++) {
firstBatch.add(new NodeAndValue(nodeId++, stringValue(prefix + i + " " + i)));
}
withPopulator(indexProvider.getPopulator(descriptor, indexSamplingConfig, heapBufferFactory(1024), INSTANCE, tokenNameLookup), p -> {
p.add(updates(firstBatch), NULL);
p.add(updates(secondBatch), NULL);
// Index should be consistent
});
List<NodeAndValue> toRemove = new ArrayList<>();
toRemove.addAll(firstBatch);
toRemove.addAll(secondBatch);
Collections.shuffle(toRemove);
// And we should be able to remove the entries in any order
try (IndexAccessor accessor = indexProvider.getOnlineAccessor(descriptor, indexSamplingConfig, tokenNameLookup)) {
// WHEN
try (IndexUpdater updater = accessor.newUpdater(IndexUpdateMode.ONLINE, NULL)) {
for (NodeAndValue nodeAndValue : toRemove) {
updater.process(IndexEntryUpdate.remove(nodeAndValue.nodeId, descriptor, nodeAndValue.value));
}
}
// THEN
try (ValueIndexReader reader = accessor.newValueReader()) {
int propertyKeyId = descriptor.schema().getPropertyId();
for (NodeAndValue nodeAndValue : toRemove) {
NodeValueIterator nodes = new NodeValueIterator();
reader.query(NULL_CONTEXT, nodes, unconstrained(), PropertyIndexQuery.exact(propertyKeyId, nodeAndValue.value));
boolean anyHits = false;
StringJoiner nodesStillLeft = new StringJoiner(", ", "[", "]");
while (nodes.hasNext()) {
anyHits = true;
nodesStillLeft.add(Long.toString(nodes.next()));
}
assertFalse("Expected this query to have zero hits but found " + nodesStillLeft, anyHits);
}
}
}
}
use of org.neo4j.kernel.impl.index.schema.NodeValueIterator in project neo4j by neo4j.
the class NonUniqueDatabaseIndexPopulatorTest method addUpdates.
@Test
void addUpdates() throws Exception {
populator = newPopulator();
List<IndexEntryUpdate<?>> updates = Arrays.asList(add(1, labelSchemaDescriptor, "foo"), add(2, labelSchemaDescriptor, "bar"), add(42, labelSchemaDescriptor, "bar"));
populator.add(updates, NULL);
index.maybeRefreshBlocking();
try (ValueIndexReader reader = index.getIndexReader();
NodeValueIterator allEntities = new NodeValueIterator()) {
int propertyKeyId = labelSchemaDescriptor.getPropertyId();
reader.query(NULL_CONTEXT, allEntities, unconstrained(), PropertyIndexQuery.exists(propertyKeyId));
assertArrayEquals(new long[] { 1, 2, 42 }, PrimitiveLongCollections.asArray(allEntities));
}
}
Aggregations