2222import org .junit .jupiter .api .Test ;
2323import org .neo4j .gds .BaseTest ;
2424import org .neo4j .gds .NodeProjections ;
25+ import org .neo4j .gds .PropertyMapping ;
26+ import org .neo4j .gds .PropertyMappings ;
2527import org .neo4j .gds .RelationshipProjection ;
2628import org .neo4j .gds .RelationshipProjections ;
2729import org .neo4j .gds .RelationshipType ;
2830import org .neo4j .gds .api .AdjacencyList ;
31+ import org .neo4j .gds .api .AdjacencyProperties ;
2932import org .neo4j .gds .api .GraphLoaderContext ;
3033import org .neo4j .gds .api .ImmutableGraphLoaderContext ;
3134import org .neo4j .gds .compat .GraphDatabaseApiProxy ;
4649import org .neo4j .internal .id .IdGeneratorFactory ;
4750import org .neo4j .logging .NullLog ;
4851
52+ import java .util .function .LongToIntFunction ;
53+
4954import static org .assertj .core .api .Assertions .assertThat ;
5055
5156class ScanningRelationshipsImporterTest extends BaseTest {
5257
5358 @ Neo4jGraph
5459 public static final String DB = "CREATE " +
55- "(a)-[:R]->(b)," +
56- "(a)-[:R]->(c)," +
57- "(a)-[:R]->(d)," +
58- "(b)-[:R]->(c)," +
59- "(c)-[:R]->(a)" ;
60+ "(a)-[:R { p: 1.0 } ]->(b)," +
61+ "(a)-[:R { p: 2.0 } ]->(c)," +
62+ "(a)-[:R { p: 3.0 } ]->(d)," +
63+ "(b)-[:R { p: 4.0 } ]->(c)," +
64+ "(c)-[:R { p: 5.0 } ]->(a)" ;
6065
6166 @ Inject
6267 private IdFunction idFunction ;
@@ -101,10 +106,55 @@ void shouldLoadInverseRelationships() {
101106 assertThat (degree ("c" , inverseAdjacencyList )).isEqualTo (2 ); // (a)-->(c),(b)-->(c)
102107 assertThat (degree ("d" , inverseAdjacencyList )).isEqualTo (1 ); // (a)-->(d)
103108
104- assertThat (targets ("a" , inverseAdjacencyList )).isEqualTo (nodeIds ("c" )); // (c)-->(a)
105- assertThat (targets ("b" , inverseAdjacencyList )).isEqualTo (nodeIds ("a" )); // (a)-->(b)
106- assertThat (targets ("c" , inverseAdjacencyList )).isEqualTo (nodeIds ("a" , "b" )); // (a)-->(c),(b)-->(c)
107- assertThat (targets ("d" , inverseAdjacencyList )).isEqualTo (nodeIds ("a" )); // (a)-->(d)
109+ assertThat (targets ("a" , inverseAdjacencyList )).isEqualTo (nodeIds ("c" )); // (c)-->(a)
110+ assertThat (targets ("b" , inverseAdjacencyList )).isEqualTo (nodeIds ("a" )); // (a)-->(b)
111+ assertThat (targets ("c" , inverseAdjacencyList )).isEqualTo (nodeIds ("a" , "b" )); // (a)-->(c),(b)-->(c)
112+ assertThat (targets ("d" , inverseAdjacencyList )).isEqualTo (nodeIds ("a" )); // (a)-->(d)
113+ }
114+
115+ @ Test
116+ void shouldLoadInverseRelationshipsWithProperties () {
117+ var relationshipType = RelationshipType .of ("R" );
118+ var graphProjectConfig = ImmutableGraphProjectFromStoreConfig .builder ()
119+ .graphName ("testGraph" )
120+ .nodeProjections (NodeProjections .ALL )
121+ .relationshipProjections (
122+ RelationshipProjections .single (
123+ relationshipType ,
124+ RelationshipProjection .builder ()
125+ .type ("R" )
126+ .indexInverse (true )
127+ .properties (PropertyMappings .of (PropertyMapping .of ("p" )))
128+ .build ()
129+ ))
130+ .build ();
131+
132+ var graphLoaderContext = graphLoaderContext ();
133+ var graphDimensions = graphDimensions (graphProjectConfig , graphLoaderContext );
134+ var importer = new ScanningRelationshipsImporterBuilder ()
135+ .idMap (new DirectIdMap (graphDimensions .nodeCount ()))
136+ .loadingContext (graphLoaderContext )
137+ .progressTracker (ProgressTracker .NULL_TRACKER )
138+ .dimensions (graphDimensions )
139+ .concurrency (1 )
140+ .graphProjectConfig (graphProjectConfig )
141+ .build ();
142+
143+ var relationshipsAndProperties = importer .call ();
144+
145+ var adjacencyList = relationshipsAndProperties .relationships ().get (relationshipType ).adjacencyList ();
146+ var properties = relationshipsAndProperties .properties ()
147+ .get (relationshipType )
148+ .get ("p" )
149+ .values ()
150+ .propertiesList ();
151+
152+ //@formatter:off
153+ assertThat (properties ("a" , properties , adjacencyList ::degree )).containsExactly (5.0 ); // (c)-[5.0]->(a)
154+ assertThat (properties ("b" , properties , adjacencyList ::degree )).containsExactly (1.0 ); // (a)-[1.0]->(b)
155+ assertThat (properties ("c" , properties , adjacencyList ::degree )).containsExactly (2.0 , 4.0 ); // (a)-[2.0]->(c),(b)-[4.0]->(c)
156+ assertThat (properties ("d" , properties , adjacencyList ::degree )).containsExactly (3.0 ); // (a)-[3.0->(d)
157+ //@formatter:on
108158 }
109159
110160 private int degree (String nodeVariable , AdjacencyList adjacencyList ) {
@@ -124,6 +174,22 @@ private long[] targets(String nodeVariable, AdjacencyList adjacencyList) {
124174 return targets ;
125175 }
126176
177+ private double [] properties (
178+ String nodeVariable ,
179+ AdjacencyProperties adjacencyProperties ,
180+ LongToIntFunction degrees
181+ ) {
182+ var nodeId = idFunction .of (nodeVariable );
183+ var degree = degrees .applyAsInt (nodeId );
184+ var properties = new double [degree ];
185+ var cursor = adjacencyProperties .propertyCursor (nodeId );
186+ int i = 0 ;
187+ while (cursor .hasNextLong ()) {
188+ properties [i ++] = Double .longBitsToDouble (cursor .nextLong ());
189+ }
190+ return properties ;
191+ }
192+
127193 private long [] nodeIds (String ... nodeVariables ) {
128194 var nodeIds = new long [nodeVariables .length ];
129195 for (int i = 0 ; i < nodeVariables .length ; i ++) {
0 commit comments