Skip to content

Commit e4d8aa5

Browse files
authored
Vector indexes (#856)
1 parent fcde9bf commit e4d8aa5

File tree

6 files changed

+79
-29
lines changed

6 files changed

+79
-29
lines changed

common/src/main/java/apoc/util/Util.java

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@
108108
import org.neo4j.graphdb.TransactionTerminatedException;
109109
import org.neo4j.graphdb.schema.ConstraintType;
110110
import org.neo4j.graphdb.schema.IndexDefinition;
111-
import org.neo4j.graphdb.schema.IndexType;
112111
import org.neo4j.graphdb.security.URLAccessChecker;
113112
import org.neo4j.graphdb.security.URLAccessValidationError;
114113
import org.neo4j.internal.kernel.api.procs.ProcedureCallContext;
@@ -1327,37 +1326,16 @@ public static int indexOf(List<Object> list, Object value) {
13271326
.orElse(-1);
13281327
}
13291328

1330-
/*
1331-
* Get all indexes from Neo4j
1332-
* Currently filters out vector indexes
1333-
* When vector indexes are supported, this can be changed to transaction.schema().getIndexes()
1334-
*/
13351329
public static Iterable<IndexDefinition> getIndexes(Transaction transaction) {
1336-
return StreamSupport.stream(transaction.schema().getIndexes().spliterator(), false)
1337-
.filter(indexDefinition -> indexDefinition.getIndexType() != IndexType.VECTOR)
1338-
.toList();
1330+
return transaction.schema().getIndexes();
13391331
}
13401332

1341-
/*
1342-
* Get all indexes from Neo4j for a given label
1343-
* Currently filters out vector indexes
1344-
* When vector indexes are supported, this can be changed to transaction.schema().getIndexes(label)
1345-
*/
13461333
public static Iterable<IndexDefinition> getIndexes(Transaction transaction, Label label) {
1347-
return StreamSupport.stream(transaction.schema().getIndexes(label).spliterator(), false)
1348-
.filter(indexDefinition -> indexDefinition.getIndexType() != IndexType.VECTOR)
1349-
.toList();
1334+
return transaction.schema().getIndexes(label);
13501335
}
13511336

1352-
/*
1353-
* Get all indexes from Neo4j for a given relationship type
1354-
* Currently filters out vector indexes
1355-
* When vector indexes are supported, this can be changed to transaction.schema().getIndexes(relType)
1356-
*/
13571337
public static Iterable<IndexDefinition> getIndexes(Transaction transaction, RelationshipType relType) {
1358-
return StreamSupport.stream(transaction.schema().getIndexes(relType).spliterator(), false)
1359-
.filter(indexDefinition -> indexDefinition.getIndexType() != IndexType.VECTOR)
1360-
.toList();
1338+
return transaction.schema().getIndexes(relType);
13611339
}
13621340

13631341
public static <T> T withBackOffRetries(Supplier<T> func, long initialTimeout, long upperTimeout, Log log) {

core/src/main/java/apoc/schema/Schemas.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ public List<AssertSchemaResult> assertIndexes(
200200

201201
for (IndexDefinition definition : Util.getIndexes(tx)) {
202202
if (definition.getIndexType() == IndexType.LOOKUP) continue;
203+
// Don't drop vector indexes
204+
if (definition.getIndexType() == IndexType.VECTOR) continue;
203205
if (definition.isConstraintIndex()) continue;
204206
if (definition.isMultiTokenIndex()) continue;
205207

core/src/test/java/apoc/meta/MetaTest.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ public class MetaTest {
8989
"apoc.meta.graph.of",
9090
"apoc.meta.graphSample",
9191
"apoc.meta.subGraph"))
92-
.withSetting(GraphDatabaseInternalSettings.cypher_enable_vector_type, true)
9392
.withSetting(GraphDatabaseInternalSettings.latest_kernel_version, Byte.MAX_VALUE)
9493
.withSetting(GraphDatabaseInternalSettings.latest_runtime_version, Integer.MAX_VALUE)
9594
.withSetting(
@@ -541,6 +540,42 @@ public void testMetaGraph2() {
541540
});
542541
}
543542

543+
@Test
544+
public void testVectorIndexes() {
545+
db.executeTransactionally(
546+
"""
547+
CREATE VECTOR INDEX moviePlots IF NOT EXISTS
548+
FOR (m:Movie)
549+
ON m.embedding
550+
OPTIONS { indexConfig: {
551+
`vector.dimensions`: 1536,
552+
`vector.similarity_function`: 'cosine'
553+
}}
554+
""");
555+
556+
db.executeTransactionally("CREATE (m:Movie {name:'The Movie', embedding: [1, 2, 3]})");
557+
558+
TestUtil.testResult(
559+
db,
560+
"""
561+
CALL apoc.meta.data()
562+
YIELD label, property, count, unique, index, existence, type, array, left, right, other, otherLabels, elementType
563+
RETURN * ORDER BY elementType, property""",
564+
(r) -> {
565+
Map<String, Object> row = r.next();
566+
assertEquals("node", row.get("elementType"));
567+
assertEquals("embedding", row.get("property"));
568+
assertEquals("Movie", row.get("label"));
569+
assertEquals(true, row.get("index"));
570+
row = r.next();
571+
assertEquals("node", row.get("elementType"));
572+
assertEquals("name", row.get("property"));
573+
assertEquals("Movie", row.get("label"));
574+
assertEquals(false, row.get("index"));
575+
assertFalse(r.hasNext());
576+
});
577+
}
578+
544579
@Test
545580
public void testMetaData() {
546581
db.executeTransactionally("create index for (n:Movie) on (n.title)");

core/src/test/java/apoc/periodic/PeriodicTest.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -947,7 +947,7 @@ public void testTruncate() {
947947
createDatasetForTruncate();
948948

949949
TestUtil.testCallEmpty(db, "CALL apoc.periodic.truncate", Collections.emptyMap());
950-
assertCountEntitiesAndIndexes(0, 0, 4, 2);
950+
assertCountEntitiesAndIndexes(0, 0, 5, 2);
951951

952952
dropSchema();
953953

@@ -1007,10 +1007,20 @@ private void createDatasetForTruncate() {
10071007
db.executeTransactionally("CREATE CONSTRAINT FOR (a:Two) REQUIRE a.surname IS UNIQUE");
10081008
db.executeTransactionally("CREATE INDEX FOR (n:Three) ON (n.other)");
10091009
db.executeTransactionally("CREATE CONSTRAINT FOR (a:Actor) REQUIRE a.name IS UNIQUE");
1010+
db.executeTransactionally(
1011+
"""
1012+
CREATE VECTOR INDEX moviePlots IF NOT EXISTS
1013+
FOR (m:Movie)
1014+
ON m.embedding
1015+
OPTIONS { indexConfig: {
1016+
`vector.dimensions`: 1536,
1017+
`vector.similarity_function`: 'cosine'
1018+
}}
1019+
""");
10101020

10111021
final int expectedNodes = iterations * 3;
10121022
final int expectedRels = iterations * 2;
1013-
assertCountEntitiesAndIndexes(expectedNodes, expectedRels, 4, 2);
1023+
assertCountEntitiesAndIndexes(expectedNodes, expectedRels, 5, 2);
10141024
}
10151025

10161026
private void assertCountEntitiesAndIndexes(

core/src/test/java/apoc/schema/SchemasTest.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,32 @@ public void testDropIndexWhenUsingDropExisting() {
141141
}
142142
}
143143

144+
@Test
145+
public void testDropIndexDoesntAffectVectorIndexes() {
146+
db.executeTransactionally("CREATE INDEX FOR (n:Foo) ON (n.bar)");
147+
db.executeTransactionally(
148+
"""
149+
CREATE VECTOR INDEX moviePlots IF NOT EXISTS
150+
FOR (m:Movie)
151+
ON m.embedding
152+
OPTIONS { indexConfig: {
153+
`vector.dimensions`: 1536,
154+
`vector.similarity_function`: 'cosine'
155+
}}
156+
""");
157+
testCall(db, "CALL apoc.schema.assert(null,null)", (r) -> {
158+
assertEquals("Foo", r.get("label"));
159+
assertEquals("bar", r.get("key"));
160+
assertEquals(false, r.get("unique"));
161+
assertEquals("DROPPED", r.get("action"));
162+
});
163+
try (Transaction tx = db.beginTx()) {
164+
List<IndexDefinition> indexes = Iterables.asList(tx.schema().getIndexes());
165+
// the multi-token idx remains
166+
assertEquals(1, indexes.size());
167+
}
168+
}
169+
144170
@Test
145171
public void testDropIndexAndCreateIndexWhenUsingDropExisting() {
146172
db.executeTransactionally("CREATE INDEX FOR (n:Foo) ON (n.bar)");

core/src/test/java/apoc/util/UtilsTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ public class UtilsTest {
6464

6565
@ClassRule
6666
public static DbmsRule db = new ImpermanentDbmsRule()
67-
.withSetting(GraphDatabaseInternalSettings.cypher_enable_vector_type, true)
6867
.withSetting(GraphDatabaseInternalSettings.latest_kernel_version, Byte.MAX_VALUE)
6968
.withSetting(GraphDatabaseInternalSettings.latest_runtime_version, Integer.MAX_VALUE);
7069

0 commit comments

Comments
 (0)