1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.neo4j.server.rest.web;
21
22 import static org.hamcrest.Matchers.hasKey;
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertFalse;
25 import static org.junit.Assert.assertNotNull;
26 import static org.junit.Assert.assertNull;
27 import static org.junit.Assert.assertThat;
28 import static org.junit.Assert.assertTrue;
29 import static org.junit.Assert.fail;
30 import static org.neo4j.helpers.collection.MapUtil.map;
31 import static org.neo4j.server.rest.repr.RepresentationTestBase.serialize;
32
33 import java.io.File;
34 import java.io.IOException;
35 import java.util.Arrays;
36 import java.util.Collection;
37 import java.util.Collections;
38 import java.util.HashMap;
39 import java.util.List;
40 import java.util.Map;
41
42 import org.apache.commons.io.FileUtils;
43 import org.junit.After;
44 import org.junit.Before;
45 import org.junit.Test;
46 import org.neo4j.graphdb.DynamicRelationshipType;
47 import org.neo4j.graphdb.Node;
48 import org.neo4j.graphdb.NotFoundException;
49 import org.neo4j.graphdb.PropertyContainer;
50 import org.neo4j.graphdb.Relationship;
51 import org.neo4j.graphdb.Transaction;
52 import org.neo4j.helpers.collection.MapUtil;
53 import org.neo4j.server.ServerTestUtils;
54 import org.neo4j.server.database.Database;
55 import org.neo4j.server.database.DatabaseBlockedException;
56 import org.neo4j.server.rest.domain.EndNodeNotFoundException;
57 import org.neo4j.server.rest.domain.GraphDbHelper;
58 import org.neo4j.server.rest.domain.StartNodeNotFoundException;
59 import org.neo4j.server.rest.domain.StartNodeSameAsEndNodeException;
60 import org.neo4j.server.rest.domain.TraverserReturnType;
61 import org.neo4j.server.rest.repr.BadInputException;
62 import org.neo4j.server.rest.repr.ListRepresentation;
63 import org.neo4j.server.rest.repr.NodeRepresentation;
64 import org.neo4j.server.rest.repr.NodeRepresentationTest;
65 import org.neo4j.server.rest.repr.RelationshipRepresentationTest;
66 import org.neo4j.server.rest.web.DatabaseActions.RelationshipDirection;
67
68 public class DatabaseActionsTest
69 {
70 private DatabaseActions actions;
71 private GraphDbHelper graphdbHelper;
72 private Database database;
73 private String databasePath;
74
75 @Before
76 public void clearDb() throws IOException
77 {
78 databasePath = ServerTestUtils.createTempDir().getAbsolutePath();
79 database = new Database( ServerTestUtils.EMBEDDED_GRAPH_DATABASE_FACTORY, databasePath );
80
81 graphdbHelper = new GraphDbHelper( database );
82 this.actions = new DatabaseActions( database );
83 }
84
85 @After
86 public void shutdownDatabase() throws IOException
87 {
88 this.database.shutdown();
89 FileUtils.forceDelete( new File( databasePath ) );
90 }
91
92 private long createNode( Map<String, Object> properties ) throws DatabaseBlockedException
93 {
94
95 long nodeId;
96 Transaction tx = database.graph.beginTx();
97 try
98 {
99 Node node = database.graph.createNode();
100 for ( Map.Entry<String, Object> entry : properties.entrySet() )
101 {
102 node.setProperty( entry.getKey(), entry.getValue() );
103 }
104 nodeId = node.getId();
105 tx.success();
106 } finally
107 {
108 tx.finish();
109 }
110 return nodeId;
111 }
112
113
114 @Test
115 public void createdNodeShouldBeInDatabase() throws Exception
116 {
117 NodeRepresentation noderep = actions.createNode( Collections.<String, Object>emptyMap() );
118
119 Transaction tx = database.graph.beginTx();
120 try
121 {
122 assertNotNull( database.graph.getNodeById( noderep.getId() ) );
123 } finally
124 {
125 tx.finish();
126 }
127 }
128
129 @Test
130 public void nodeInDatabaseShouldBeRetreivable() throws DatabaseBlockedException,
131 NodeNotFoundException
132 {
133 long nodeId = new GraphDbHelper( database ).createNode();
134 assertNotNull( actions.getNode( nodeId ) );
135 }
136
137 @Test
138 public void shouldBeAbleToStorePropertiesInAnExistingNode() throws DatabaseBlockedException,
139 PropertyValueException, NodeNotFoundException
140 {
141 long nodeId = graphdbHelper.createNode();
142 Map<String, Object> properties = new HashMap<String, Object>();
143 properties.put( "foo", "bar" );
144 properties.put( "baz", 17 );
145 actions.setAllNodeProperties( nodeId, properties );
146
147 Transaction tx = database.graph.beginTx();
148 try
149 {
150 Node node = database.graph.getNodeById( nodeId );
151 assertHasProperties( node, properties );
152 } finally
153 {
154 tx.finish();
155 }
156 }
157
158
159 @Test(expected = PropertyValueException.class)
160 public void shouldFailOnTryingToStoreMixedArraysAsAProperty() throws Exception
161 {
162 long nodeId = graphdbHelper.createNode();
163 Map<String, Object> properties = new HashMap<String, Object>();
164 Object[] dodgyArray = new Object[3];
165 dodgyArray[0] = 0;
166 dodgyArray[1] = 1;
167 dodgyArray[2] = "two";
168 properties.put( "foo", dodgyArray);
169
170 actions.setAllNodeProperties( nodeId, properties );
171 }
172
173 @Test
174 public void shouldOverwriteExistingProperties() throws DatabaseBlockedException,
175 PropertyValueException, NodeNotFoundException
176 {
177
178 long nodeId;
179 Transaction tx = database.graph.beginTx();
180 try
181 {
182 Node node = database.graph.createNode();
183 node.setProperty( "remove me", "trash" );
184 nodeId = node.getId();
185 tx.success();
186 } finally
187 {
188 tx.finish();
189 }
190 Map<String, Object> properties = new HashMap<String, Object>();
191 properties.put( "foo", "bar" );
192 properties.put( "baz", 17 );
193 actions.setAllNodeProperties( nodeId, properties );
194 tx = database.graph.beginTx();
195 try
196 {
197 Node node = database.graph.getNodeById( nodeId );
198 assertHasProperties( node, properties );
199 assertNull( node.getProperty( "remove me", null ) );
200 } finally
201 {
202 tx.finish();
203 }
204 }
205
206 @Test
207 public void shouldBeAbleToGetPropertiesOnNode() throws DatabaseBlockedException,
208 NodeNotFoundException
209 {
210
211 long nodeId;
212 Map<String, Object> properties = new HashMap<String, Object>();
213 properties.put( "foo", "bar" );
214 properties.put( "neo", "Thomas A. Anderson" );
215 properties.put( "number", 15L );
216 Transaction tx = database.graph.beginTx();
217 try
218 {
219 Node node = database.graph.createNode();
220 for ( Map.Entry<String, Object> entry : properties.entrySet() )
221 {
222 node.setProperty( entry.getKey(), entry.getValue() );
223 }
224 nodeId = node.getId();
225 tx.success();
226 } finally
227 {
228 tx.finish();
229 }
230
231 Map<String, Object> readProperties = serialize( actions.getAllNodeProperties( nodeId ) );
232 assertEquals( properties, readProperties );
233 }
234
235 @Test
236 public void shouldRemoveNodeWithNoRelationsFromDBOnDelete() throws DatabaseBlockedException,
237 NodeNotFoundException, OperationFailureException
238 {
239 long nodeId;
240 Transaction tx = database.graph.beginTx();
241 try
242 {
243 Node node = database.graph.createNode();
244 nodeId = node.getId();
245 tx.success();
246 } finally
247 {
248 tx.finish();
249 }
250
251 int nodeCount = graphdbHelper.getNumberOfNodes();
252 actions.deleteNode( nodeId );
253 assertEquals( nodeCount - 1, graphdbHelper.getNumberOfNodes() );
254 }
255
256 @Test
257 public void shouldBeAbleToSetPropertyOnNode() throws DatabaseBlockedException,
258 PropertyValueException, NodeNotFoundException
259 {
260 long nodeId = createNode( Collections.<String, Object>emptyMap() );
261 String key = "foo";
262 Object value = "bar";
263 actions.setNodeProperty( nodeId, key, value );
264 assertEquals( Collections.singletonMap( key, value ), graphdbHelper.getNodeProperties( nodeId ) );
265 }
266
267 @Test
268 public void shouldBeAbleToGetPropertyOnNode() throws DatabaseBlockedException,
269 NodeNotFoundException, NoSuchPropertyException, BadInputException
270 {
271 String key = "foo";
272 Object value = "bar";
273 long nodeId = createNode( Collections.singletonMap( key, value ) );
274 assertEquals( value, serialize( actions.getNodeProperty( nodeId, key ) ) );
275 }
276
277 @Test
278 public void shouldBeAbleToRemoveNodeProperties() throws DatabaseBlockedException,
279 NodeNotFoundException
280 {
281 Map<String, Object> properties = new HashMap<String, Object>();
282 properties.put( "foo", "bar" );
283 properties.put( "number", 15 );
284 long nodeId = createNode( properties );
285 actions.removeAllNodeProperties( nodeId );
286
287 Transaction tx = database.graph.beginTx();
288 try
289 {
290 Node node = database.graph.getNodeById( nodeId );
291 assertEquals( false, node.getPropertyKeys().iterator().hasNext() );
292 tx.success();
293 } finally
294 {
295 tx.finish();
296 }
297 }
298
299 @Test
300 public void shouldStoreRelationshipsBetweenTwoExistingNodes() throws Exception
301 {
302 int relationshipCount = graphdbHelper.getNumberOfRelationships();
303 actions.createRelationship( graphdbHelper.createNode(), graphdbHelper.createNode(),
304 "LOVES", Collections.<String, Object>emptyMap() );
305 assertEquals( relationshipCount + 1, graphdbHelper.getNumberOfRelationships() );
306 }
307
308 @Test
309 public void shouldStoreSuppliedPropertiesWhenCreatingRelationship() throws Exception
310 {
311 Map<String, Object> properties = new HashMap<String, Object>();
312 properties.put( "string", "value" );
313 properties.put( "integer", 17 );
314 long relId = actions.createRelationship( graphdbHelper.createNode(),
315 graphdbHelper.createNode(), "LOVES", properties ).getId();
316
317 Transaction tx = database.graph.beginTx();
318 try
319 {
320 Relationship rel = database.graph.getRelationshipById( relId );
321 for ( String key : rel.getPropertyKeys() )
322 {
323 assertTrue( "extra property stored", properties.containsKey( key ) );
324 }
325 for ( Map.Entry<String, Object> entry : properties.entrySet() )
326 {
327 assertEquals( entry.getValue(), rel.getProperty( entry.getKey() ) );
328 }
329 } finally
330 {
331 tx.finish();
332 }
333 }
334
335 @Test
336 public void shouldNotCreateRelationshipBetweenNonExistentNodes() throws Exception
337 {
338 long nodeId = graphdbHelper.createNode();
339 Map<String, Object> properties = Collections.<String, Object>emptyMap();
340 try
341 {
342 actions.createRelationship( nodeId, nodeId * 1000, "Loves", properties );
343 fail();
344 } catch ( EndNodeNotFoundException e )
345 {
346
347 }
348 try
349 {
350 actions.createRelationship( nodeId * 1000, nodeId, "Loves", properties );
351 fail();
352 } catch ( StartNodeNotFoundException e )
353 {
354
355 }
356 }
357
358 @Test
359 public void shouldNotCreateRelationshipWithSameStartAsEndNode() throws Exception
360 {
361 long nodeId = graphdbHelper.createNode();
362 Map<String, Object> properties = Collections.<String, Object>emptyMap();
363 try
364 {
365 actions.createRelationship( nodeId, nodeId, "Loves", properties );
366 fail();
367 } catch ( StartNodeSameAsEndNodeException e )
368 {
369
370 }
371 }
372
373 @Test
374 public void shouldBeAbleToRemoveNodeProperty() throws DatabaseBlockedException,
375 NodeNotFoundException, NoSuchPropertyException
376 {
377 Map<String, Object> properties = new HashMap<String, Object>();
378 properties.put( "foo", "bar" );
379 properties.put( "number", 15 );
380 long nodeId = createNode( properties );
381 actions.removeNodeProperty( nodeId, "foo" );
382
383 Transaction tx = database.graph.beginTx();
384 try
385 {
386 Node node = database.graph.getNodeById( nodeId );
387 assertEquals( 15, node.getProperty( "number" ) );
388 assertEquals( false, node.hasProperty( "foo" ) );
389 tx.success();
390 } finally
391 {
392 tx.finish();
393 }
394 }
395
396 @Test
397 public void shouldReturnTrueIfNodePropertyRemoved() throws DatabaseBlockedException,
398 NodeNotFoundException, NoSuchPropertyException
399 {
400 Map<String, Object> properties = new HashMap<String, Object>();
401 properties.put( "foo", "bar" );
402 properties.put( "number", 15 );
403 long nodeId = createNode( properties );
404 actions.removeNodeProperty( nodeId, "foo" );
405 }
406
407 @Test( expected = NoSuchPropertyException.class )
408 public void shouldReturnFalseIfNodePropertyNotRemoved() throws DatabaseBlockedException,
409 NodeNotFoundException, NoSuchPropertyException
410 {
411 Map<String, Object> properties = new HashMap<String, Object>();
412 properties.put( "foo", "bar" );
413 properties.put( "number", 15 );
414 long nodeId = createNode( properties );
415 actions.removeNodeProperty( nodeId, "baz" );
416 }
417
418 @Test
419 public void shouldBeAbleToRetrieveARelationship() throws DatabaseBlockedException,
420 RelationshipNotFoundException
421 {
422 long relationship = graphdbHelper.createRelationship( "ENJOYED" );
423 assertNotNull( actions.getRelationship( relationship ) );
424 }
425
426 @Test
427 public void shouldBeAbleToGetPropertiesOnRelationship() throws DatabaseBlockedException,
428 RelationshipNotFoundException
429 {
430
431 long relationshipId;
432 Map<String, Object> properties = new HashMap<String, Object>();
433 properties.put( "foo", "bar" );
434 properties.put( "neo", "Thomas A. Anderson" );
435 properties.put( "number", 15L );
436 Transaction tx = database.graph.beginTx();
437 try
438 {
439 Node startNode = database.graph.createNode();
440 Node endNode = database.graph.createNode();
441 Relationship relationship = startNode.createRelationshipTo( endNode, DynamicRelationshipType.withName( "knows" ) );
442 for ( Map.Entry<String, Object> entry : properties.entrySet() )
443 {
444 relationship.setProperty( entry.getKey(), entry.getValue() );
445 }
446 relationshipId = relationship.getId();
447 tx.success();
448 } finally
449 {
450 tx.finish();
451 }
452
453 Map<String, Object> readProperties = serialize( actions.getAllRelationshipProperties( relationshipId ) );
454 assertEquals( properties, readProperties );
455 }
456
457 @Test
458 public void shouldBeAbleToRetrieveASinglePropertyFromARelationship()
459 throws DatabaseBlockedException, NoSuchPropertyException, RelationshipNotFoundException, BadInputException
460 {
461 Map<String, Object> properties = new HashMap<String, Object>();
462 properties.put( "foo", "bar" );
463 properties.put( "neo", "Thomas A. Anderson" );
464 properties.put( "number", 15L );
465
466 long relationshipId = graphdbHelper.createRelationship( "LOVES" );
467 graphdbHelper.setRelationshipProperties( relationshipId, properties );
468
469 Object relationshipProperty = serialize( actions.getRelationshipProperty( relationshipId, "foo" ) );
470 assertEquals( "bar", relationshipProperty );
471 }
472
473 @Test
474 public void shouldBeAbleToDeleteARelationship() throws DatabaseBlockedException,
475 RelationshipNotFoundException
476 {
477 long relationshipId = graphdbHelper.createRelationship( "LOVES" );
478
479 actions.deleteRelationship( relationshipId );
480 try
481 {
482 graphdbHelper.getRelationship( relationshipId );
483 fail();
484 } catch ( NotFoundException e )
485 {
486 }
487 }
488
489 @Test
490 public void shouldBeAbleToRetrieveRelationshipsFromNode() throws DatabaseBlockedException,
491 NodeNotFoundException
492 {
493 long nodeId = graphdbHelper.createNode();
494 graphdbHelper.createRelationship( "LIKES", nodeId, graphdbHelper.createNode() );
495 graphdbHelper.createRelationship( "LIKES", graphdbHelper.createNode(), nodeId );
496 graphdbHelper.createRelationship( "HATES", nodeId, graphdbHelper.createNode() );
497
498 verifyRelReps( 3, actions.getNodeRelationships( nodeId, RelationshipDirection.all,
499 Collections.<String>emptyList() ) );
500 verifyRelReps( 1, actions.getNodeRelationships( nodeId, RelationshipDirection.in,
501 Collections.<String>emptyList() ) );
502 verifyRelReps( 2, actions.getNodeRelationships( nodeId, RelationshipDirection.out,
503 Collections.<String>emptyList() ) );
504
505 verifyRelReps( 3, actions.getNodeRelationships( nodeId, RelationshipDirection.all,
506 Arrays.asList( "LIKES", "HATES" ) ) );
507 verifyRelReps( 1, actions.getNodeRelationships( nodeId, RelationshipDirection.in,
508 Arrays.asList( "LIKES", "HATES" ) ) );
509 verifyRelReps( 2, actions.getNodeRelationships( nodeId, RelationshipDirection.out,
510 Arrays.asList( "LIKES", "HATES" ) ) );
511
512 verifyRelReps( 2, actions.getNodeRelationships( nodeId, RelationshipDirection.all,
513 Arrays.asList( "LIKES" ) ) );
514 verifyRelReps( 1, actions.getNodeRelationships( nodeId, RelationshipDirection.in,
515 Arrays.asList( "LIKES" ) ) );
516 verifyRelReps( 1, actions.getNodeRelationships( nodeId, RelationshipDirection.out,
517 Arrays.asList( "LIKES" ) ) );
518
519 verifyRelReps( 1, actions.getNodeRelationships( nodeId, RelationshipDirection.all,
520 Arrays.asList( "HATES" ) ) );
521 verifyRelReps( 0, actions.getNodeRelationships( nodeId, RelationshipDirection.in,
522 Arrays.asList( "HATES" ) ) );
523 verifyRelReps( 1, actions.getNodeRelationships( nodeId, RelationshipDirection.out,
524 Arrays.asList( "HATES" ) ) );
525 }
526
527 @Test
528 public void shouldNotGetAnyRelationshipsWhenRetrievingFromNodeWithoutRelationships()
529 throws DatabaseBlockedException, NodeNotFoundException
530 {
531 long nodeId = graphdbHelper.createNode();
532
533 verifyRelReps( 0, actions.getNodeRelationships( nodeId, RelationshipDirection.all,
534 Collections.<String>emptyList() ) );
535 verifyRelReps( 0, actions.getNodeRelationships( nodeId, RelationshipDirection.in,
536 Collections.<String>emptyList() ) );
537 verifyRelReps( 0, actions.getNodeRelationships( nodeId, RelationshipDirection.out,
538 Collections.<String>emptyList() ) );
539 }
540
541 @Test
542 public void shouldBeAbleToSetRelationshipProperties() throws DatabaseBlockedException,
543 PropertyValueException, RelationshipNotFoundException
544 {
545 long relationshipId = graphdbHelper.createRelationship( "KNOWS" );
546 Map<String, Object> properties = new HashMap<String, Object>();
547 properties.put( "foo", "bar" );
548 properties.put( "number", 10 );
549 actions.setAllRelationshipProperties( relationshipId, properties );
550 assertEquals( properties, graphdbHelper.getRelationshipProperties( relationshipId ) );
551 }
552
553 @Test
554 public void shouldBeAbleToSetRelationshipProperty() throws DatabaseBlockedException,
555 PropertyValueException, RelationshipNotFoundException
556 {
557 long relationshipId = graphdbHelper.createRelationship( "KNOWS" );
558 String key = "foo";
559 Object value = "bar";
560 actions.setRelationshipProperty( relationshipId, key, value );
561 assertEquals( Collections.singletonMap( key, value ), graphdbHelper.getRelationshipProperties( relationshipId ) );
562 }
563
564 @Test
565 public void shouldRemoveRelationProperties() throws DatabaseBlockedException,
566 RelationshipNotFoundException
567 {
568 long relId = graphdbHelper.createRelationship( "PAIR-PROGRAMS_WITH" );
569 Map<String, Object> map = new HashMap<String, Object>();
570 map.put( "foo", "bar" );
571 map.put( "baz", 22 );
572 graphdbHelper.setRelationshipProperties( relId, map );
573
574 actions.removeAllRelationshipProperties( relId );
575
576 assertTrue( graphdbHelper.getRelationshipProperties( relId ).isEmpty() );
577 }
578
579 @Test
580 public void shouldRemoveRelationshipProperty() throws DatabaseBlockedException,
581 RelationshipNotFoundException, NoSuchPropertyException
582 {
583 long relId = graphdbHelper.createRelationship( "PAIR-PROGRAMS_WITH" );
584 Map<String, Object> map = new HashMap<String, Object>();
585 map.put( "foo", "bar" );
586 map.put( "baz", 22 );
587 graphdbHelper.setRelationshipProperties( relId, map );
588
589 actions.removeRelationshipProperty( relId, "foo" );
590 assertEquals( 1, graphdbHelper.getRelationshipProperties( relId ).size() );
591 }
592
593 @SuppressWarnings( "unchecked" )
594 private void verifyRelReps( int expectedSize, ListRepresentation repr )
595 {
596 List<Object> relreps = serialize( repr );
597 assertEquals( expectedSize, relreps.size() );
598 for ( Object relrep : relreps )
599 {
600 RelationshipRepresentationTest.verifySerialisation( (Map<String, Object>)relrep );
601 }
602 }
603
604 private void assertHasProperties( PropertyContainer container, Map<String, Object> properties )
605 {
606 for ( Map.Entry<String, Object> entry : properties.entrySet() )
607 {
608 assertEquals( entry.getValue(), container.getProperty( entry.getKey() ) );
609 }
610 }
611
612 @Test
613 public void shouldBeAbleToIndexNode() throws DatabaseBlockedException
614 {
615 String key = "mykey";
616 String value = "myvalue";
617 long nodeId = graphdbHelper.createNode();
618 String indexName = "node";
619
620 actions.createNodeIndex( MapUtil.map( "name", indexName ) );
621
622 assertFalse( serialize( actions.getIndexedNodesByExactMatch( indexName, key, value ) ).iterator().hasNext() );
623 actions.addToNodeIndex( indexName, key, value, nodeId );
624 assertEquals( Arrays.asList( nodeId ), graphdbHelper.getIndexedNodes( indexName, key, value ) );
625 }
626
627 @Test
628 public void shouldBeAbleToFulltextIndex() throws DatabaseBlockedException
629 {
630 String key = "key";
631 String value = "the value with spaces";
632 long nodeId = graphdbHelper.createNode();
633 String indexName = "fulltext-node";
634 graphdbHelper.createNodeFullTextIndex( indexName );
635 assertFalse( serialize( actions.getIndexedNodesByExactMatch( indexName, key, value ) ).iterator().hasNext() );
636 actions.addToNodeIndex( indexName, key, value, nodeId );
637 assertEquals( Arrays.asList( nodeId ), graphdbHelper.getIndexedNodes( indexName, key, value ) );
638 assertEquals( Arrays.asList( nodeId ), graphdbHelper.getIndexedNodes( indexName, key, "the value with spaces" ) );
639 assertEquals( Arrays.asList( nodeId ), graphdbHelper.queryIndexedNodes( indexName, key, "the" ) );
640 assertEquals( Arrays.asList( nodeId ), graphdbHelper.queryIndexedNodes( indexName, key, "value" ) );
641 assertEquals( Arrays.asList( nodeId ), graphdbHelper.queryIndexedNodes( indexName, key, "with" ) );
642 assertEquals( Arrays.asList( nodeId ), graphdbHelper.queryIndexedNodes( indexName, key, "spaces" ) );
643 assertEquals( Arrays.asList( nodeId ), graphdbHelper.queryIndexedNodes( indexName, key, "*spaces*" ) );
644 assertTrue( graphdbHelper.getIndexedNodes( indexName, key, "nohit" ).isEmpty() );
645 }
646
647 @Test
648 public void shouldBeAbleToGetReferenceNode() throws DatabaseBlockedException,
649 NodeNotFoundException
650 {
651 NodeRepresentation rep = actions.getReferenceNode();
652 actions.getNode( rep.getId() );
653 }
654
655 @Test
656 public void shouldGetExtendedNodeRepresentationsWhenGettingFromIndex() throws DatabaseBlockedException
657 {
658 String key = "mykey3";
659 String value = "value";
660
661 long nodeId = graphdbHelper.createNode();
662 String indexName = "node";
663 graphdbHelper.addNodeToIndex( indexName, key, value, nodeId );
664 int counter = 0;
665 for ( Object rep : serialize( actions.getIndexedNodesByExactMatch( indexName, key, value ) ) )
666 {
667 Map<String, Object> serialized = (Map<String, Object>)rep;
668 NodeRepresentationTest.verifySerialisation( serialized );
669 assertNotNull( serialized.get( "indexed" ) );
670 counter++;
671 }
672 assertEquals( 1, counter );
673 }
674
675 @Test
676 public void shouldBeAbleToRemoveNodeFromIndex() throws DatabaseBlockedException
677 {
678 String key = "mykey2";
679 String value = "myvalue";
680 String value2 = "myvalue2";
681 String indexName = "node";
682 long nodeId = graphdbHelper.createNode();
683 actions.addToNodeIndex( indexName, key, value, nodeId );
684 actions.addToNodeIndex( indexName, key, value2, nodeId );
685 assertEquals( 1, graphdbHelper.getIndexedNodes( indexName, key, value ).size() );
686 assertEquals( 1, graphdbHelper.getIndexedNodes( indexName, key, value2 ).size() );
687 actions.removeFromNodeIndex( indexName, key, value, nodeId );
688 assertEquals( 0, graphdbHelper.getIndexedNodes( indexName, key, value ).size() );
689 assertEquals( 1, graphdbHelper.getIndexedNodes( indexName, key, value2 ).size() );
690 actions.removeFromNodeIndex( indexName, key, value2, nodeId );
691 assertEquals( 0, graphdbHelper.getIndexedNodes( indexName, key, value ).size() );
692 assertEquals( 0, graphdbHelper.getIndexedNodes( indexName, key, value2 ).size() );
693 }
694
695 @Test
696 public void shouldBeAbleToRemoveNodeFromIndexWithoutKeyValue() throws DatabaseBlockedException
697 {
698 String key1 = "kvkey1";
699 String key2 = "kvkey2";
700 String value = "myvalue";
701 String value2 = "myvalue2";
702 String indexName = "node";
703 long nodeId = graphdbHelper.createNode();
704 actions.addToNodeIndex( indexName, key1, value, nodeId );
705 actions.addToNodeIndex( indexName, key1, value2, nodeId );
706 actions.addToNodeIndex( indexName, key2, value, nodeId );
707 actions.addToNodeIndex( indexName, key2, value2, nodeId );
708 assertEquals( 1, graphdbHelper.getIndexedNodes( indexName, key1, value ).size() );
709 assertEquals( 1, graphdbHelper.getIndexedNodes( indexName, key1, value2 ).size() );
710 assertEquals( 1, graphdbHelper.getIndexedNodes( indexName, key2, value ).size() );
711 assertEquals( 1, graphdbHelper.getIndexedNodes( indexName, key2, value2 ).size() );
712 actions.removeFromNodeIndexNoValue( indexName, key1, nodeId );
713 assertEquals( 0, graphdbHelper.getIndexedNodes( indexName, key1, value ).size() );
714 assertEquals( 0, graphdbHelper.getIndexedNodes( indexName, key1, value2 ).size() );
715 assertEquals( 1, graphdbHelper.getIndexedNodes( indexName, key2, value ).size() );
716 assertEquals( 1, graphdbHelper.getIndexedNodes( indexName, key2, value2 ).size() );
717 actions.removeFromNodeIndexNoKeyValue( indexName, nodeId );
718 assertEquals( 0, graphdbHelper.getIndexedNodes( indexName, key1, value ).size() );
719 assertEquals( 0, graphdbHelper.getIndexedNodes( indexName, key1, value2 ).size() );
720 assertEquals( 0, graphdbHelper.getIndexedNodes( indexName, key2, value ).size() );
721 assertEquals( 0, graphdbHelper.getIndexedNodes( indexName, key2, value2 ).size() );
722 }
723
724 private long createBasicTraversableGraph() throws DatabaseBlockedException
725 {
726
727
728
729
730
731
732 long startNode = graphdbHelper.createNode( MapUtil.map( "name", "Root" ) );
733 long child1_l1 = graphdbHelper.createNode( MapUtil.map( "name", "Mattias" ) );
734 graphdbHelper.createRelationship( "knows", startNode, child1_l1 );
735 long child2_l1 = graphdbHelper.createNode( MapUtil.map( "name", "Johan" ) );
736 graphdbHelper.createRelationship( "knows", startNode, child2_l1 );
737 long child1_l2 = graphdbHelper.createNode( MapUtil.map( "name", "Emil" ) );
738 graphdbHelper.createRelationship( "knows", child2_l1, child1_l2 );
739 long child1_l3 = graphdbHelper.createNode( MapUtil.map( "name", "Peter" ) );
740 graphdbHelper.createRelationship( "knows", child1_l2, child1_l3 );
741 long child2_l3 = graphdbHelper.createNode( MapUtil.map( "name", "Tobias" ) );
742 graphdbHelper.createRelationship( "loves", child1_l2, child2_l3 );
743 return startNode;
744 }
745
746 private long[] createMoreComplexGraph() throws DatabaseBlockedException
747 {
748
749
750
751
752
753
754
755
756 long a = graphdbHelper.createNode();
757 long b = graphdbHelper.createNode();
758 long c = graphdbHelper.createNode();
759 long d = graphdbHelper.createNode();
760 long e = graphdbHelper.createNode();
761 long f = graphdbHelper.createNode();
762 long g = graphdbHelper.createNode();
763 graphdbHelper.createRelationship( "to", a, c );
764 graphdbHelper.createRelationship( "to", a, d );
765 graphdbHelper.createRelationship( "to", c, b );
766 graphdbHelper.createRelationship( "to", d, e );
767 graphdbHelper.createRelationship( "to", b, f );
768 graphdbHelper.createRelationship( "to", c, f );
769 graphdbHelper.createRelationship( "to", f, g );
770 graphdbHelper.createRelationship( "to", d, g );
771 graphdbHelper.createRelationship( "to", e, g );
772 graphdbHelper.createRelationship( "to", c, g );
773 return new long[]{a, g};
774 }
775
776 private void createRelationshipWithProperties( long start, long end, Map<String, Object> properties )
777 {
778 long rel = graphdbHelper.createRelationship( "to", start, end );
779 graphdbHelper.setRelationshipProperties( rel, properties );
780 }
781
782 private long[] createDijkstraGraph( boolean includeOnes ) throws DatabaseBlockedException
783 {
784
785
786
787
788
789
790
791
792
793
794
795
796 Map<String, Object> costOneProperties = includeOnes ? map( "cost", (double) 1 ) : map();
797 long start = graphdbHelper.createNode();
798 long a = graphdbHelper.createNode();
799 long b = graphdbHelper.createNode();
800 long c = graphdbHelper.createNode();
801 long d = graphdbHelper.createNode();
802 long e = graphdbHelper.createNode();
803 long f = graphdbHelper.createNode();
804 long x = graphdbHelper.createNode();
805 long y = graphdbHelper.createNode();
806
807 createRelationshipWithProperties( start, a, costOneProperties );
808 createRelationshipWithProperties( a, x, map( "cost", (double) 9 ) );
809 createRelationshipWithProperties( a, b, costOneProperties );
810 createRelationshipWithProperties( b, x, map( "cost", (double) 7 ) );
811 createRelationshipWithProperties( b, c, costOneProperties );
812 createRelationshipWithProperties( c, x, map( "cost", (double) 5 ) );
813 createRelationshipWithProperties( c, x, map( "cost", (double) 4 ) );
814 createRelationshipWithProperties( c, d, costOneProperties );
815 createRelationshipWithProperties( d, x, map( "cost", (double) 3 ) );
816 createRelationshipWithProperties( d, e, costOneProperties );
817 createRelationshipWithProperties( e, x, costOneProperties );
818 createRelationshipWithProperties( e, f, map( "cost", (double) 2 ) );
819 createRelationshipWithProperties( x, y, map( "cost", (double) 2 ) );
820 return new long[] { start, x };
821 }
822
823 @Test
824 public void shouldBeAbleToTraverseWithDefaultParameters() throws DatabaseBlockedException
825 {
826 long startNode = createBasicTraversableGraph();
827 List<Object> hits = serialize( actions.traverse( startNode, new HashMap<String, Object>(),
828 TraverserReturnType.node ) );
829 assertEquals( 2, hits.size() );
830 }
831
832 @Test
833 public void shouldBeAbleToTraverseDepthTwo() throws DatabaseBlockedException
834 {
835 long startNode = createBasicTraversableGraph();
836 List<Object> hits = serialize( actions.traverse( startNode, MapUtil.map(
837 "max depth", 2 ), TraverserReturnType.node ) );
838 assertEquals( 3, hits.size() );
839 }
840
841 @Test
842 public void shouldBeAbleToTraverseEverything() throws DatabaseBlockedException
843 {
844 long startNode = createBasicTraversableGraph();
845 List<Object> hits = serialize( actions.traverse( startNode, MapUtil.map(
846 "return filter", MapUtil.map( "language", "javascript", "body", "true;" ),
847 "max depth", 10 ), TraverserReturnType.node ) );
848 assertEquals( 6, hits.size() );
849 hits = serialize( actions.traverse( startNode, MapUtil.map( "return filter", MapUtil.map(
850 "language", "builtin", "name", "all" ), "max depth", 10 ), TraverserReturnType.node ) );
851 assertEquals( 6, hits.size() );
852 }
853
854 @Test
855 public void shouldBeAbleToUseCustomReturnFilter() throws DatabaseBlockedException
856 {
857 long startNode = createBasicTraversableGraph();
858 List<Object> hits = serialize( actions.traverse( startNode, MapUtil.map( "prune evaluator",
859 MapUtil.map( "language", "builtin", "name", "none" ),
860 "return filter", MapUtil.map( "language", "javascript", "body", "position.endNode().getProperty( 'name' ).contains( 'o' )" ) ),
861 TraverserReturnType.node ) );
862 assertEquals( 3, hits.size() );
863 }
864
865 @Test
866 public void shouldBeAbleToTraverseWithMaxDepthAndPruneEvaluatorCombined() throws DatabaseBlockedException
867 {
868 long startNode = createBasicTraversableGraph();
869 List<Object> hits = serialize( actions.traverse( startNode, MapUtil.map( "max depth", 2,
870 "prune evaluator", MapUtil.map( "language", "javascript", "body",
871 "position.endNode().getProperty('name').equals('Emil')" ) ),
872 TraverserReturnType.node ) );
873 assertEquals( 3, hits.size() );
874 hits = serialize( actions.traverse( startNode, MapUtil.map( "max depth", 1,
875 "prune evaluator", MapUtil.map( "language", "javascript", "body",
876 "position.endNode().getProperty('name').equals('Emil')" ) ),
877 TraverserReturnType.node ) );
878 assertEquals( 2, hits.size() );
879 }
880
881 @Test
882 public void shouldBeAbleToGetRelationshipsIfSpecified() throws DatabaseBlockedException
883 {
884 long startNode = createBasicTraversableGraph();
885 ListRepresentation traverse = actions.traverse( startNode, new HashMap<String, Object>(),
886 TraverserReturnType.relationship );
887 List<Object> hits = serialize( traverse );
888 for ( Object hit : hits )
889 {
890 RelationshipRepresentationTest.verifySerialisation( (Map<String, Object>)hit );
891 }
892 }
893
894 @Test
895 public void shouldBeAbleToGetPathsIfSpecified() throws DatabaseBlockedException
896 {
897 long startNode = createBasicTraversableGraph();
898 List<Object> hits = serialize( actions.traverse( startNode, new HashMap<String, Object>(),
899 TraverserReturnType.path ) );
900
901 for ( Object hit : hits )
902 {
903 Map<String, Object> map = (Map<String, Object>)hit;
904 assertThat( map, hasKey( "start" ) );
905 assertThat( map, hasKey( "end" ) );
906 assertThat( map, hasKey( "length" ) );
907 }
908 }
909 @Test
910 public void shouldBeAbleToGetFullPathsIfSpecified() throws
911 DatabaseBlockedException
912 {
913 long startNode = createBasicTraversableGraph();
914 List<Object> hits = serialize( actions.traverse( startNode, new HashMap<String, Object>(),
915 TraverserReturnType.fullpath ) );
916
917 for ( Object hit : hits )
918 {
919 Map<String, Object> map = (Map<String, Object>)hit;
920 Collection<Object> relationships= (Collection<Object>) map.get("relationships");
921 for (Object relationship : relationships)
922 {
923 RelationshipRepresentationTest.verifySerialisation(
924 (Map<String, Object>)relationship );
925 }
926 Collection<Object> nodes = (Collection<Object>) map.get("nodes");
927 for (Object node : nodes)
928 {
929 NodeRepresentationTest.verifySerialisation(
930 (Map<String, Object>)node );
931 }
932 assertThat( map, hasKey( "start" ) );
933 assertThat( map, hasKey( "end" ) );
934 assertThat( map, hasKey( "length" ) );
935 }
936 }
937
938 @Test
939 public void shouldBeAbleToGetShortestPaths() throws Exception
940 {
941 long[] nodes = createMoreComplexGraph();
942
943
944 List<Object> result = serialize( actions.findPaths( nodes[ 0 ], nodes[ 1 ], MapUtil.map(
945 "max depth", 2, "algorithm", "shortestPath", "relationships", MapUtil.map( "type",
946 "to", "direction", "out" ) ) ) );
947 assertPaths( 2, nodes, 2, result );
948
949
950 Map<String, Object> path = serialize( actions.findSinglePath( nodes[ 0 ], nodes[ 1 ],
951 MapUtil.map( "max depth", 2, "algorithm", "shortestPath", "relationships",
952 MapUtil.map( "type", "to", "direction", "out" ) ) ) );
953 assertPaths( 1, nodes, 2, Arrays.<Object>asList( path ) );
954
955
956 path = serialize( actions.findSinglePath( nodes[ 0 ], nodes[ 1 ], MapUtil.map( "max depth", 2,
957 "algorithm", "shortestPath", "relationships", MapUtil.map( "type", "to",
958 "direction", "out" ), "single", false ) ) );
959 assertPaths( 1, nodes, 2, Arrays.<Object>asList( path ) );
960 }
961
962 @Test
963 public void shouldBeAbleToGetPathsUsingDijkstra() throws Exception
964 {
965 long[] nodes = createDijkstraGraph( true );
966
967
968 List<Object> result = serialize( actions.findPaths( nodes[ 0 ], nodes[ 1 ], map(
969 "algorithm", "dijkstra", "cost property", "cost", "relationships", map( "type",
970 "to", "direction", "out" ) ) ) );
971 assertPaths( 1, nodes, 6, result );
972
973
974 Map<String, Object> path = serialize( actions.findSinglePath( nodes[ 0 ], nodes[ 1 ],
975 map( "algorithm", "dijkstra", "cost property", "cost", "relationships",
976 map( "type", "to", "direction", "out" ) ) ) );
977 assertPaths( 1, nodes, 6, Arrays.<Object>asList( path ) );
978 assertEquals( 6.0d, path.get( "weight" ) );
979 }
980
981 @Test
982 public void shouldBeAbleToGetPathsUsingDijkstraWithDefaults() throws Exception
983 {
984 long[] nodes = createDijkstraGraph( false );
985
986
987 List<Object> result = serialize( actions.findPaths( nodes[ 0 ], nodes[ 1 ], map(
988 "algorithm", "dijkstra", "cost property", "cost", "default cost", 1,
989 "relationships", map( "type", "to", "direction", "out" ) ) ) );
990 assertPaths( 1, nodes, 6, result );
991
992
993 Map<String, Object> path = serialize( actions.findSinglePath( nodes[ 0 ], nodes[ 1 ],
994 map( "algorithm", "dijkstra", "cost property", "cost", "default cost", 1,
995 "relationships", map( "type", "to", "direction", "out" ) ) ) );
996 assertPaths( 1, nodes, 6, Arrays.<Object>asList( path ) );
997 assertEquals( 6.0d, path.get( "weight" ) );
998 }
999
1000 @Test( expected = NotFoundException.class )
1001 public void shouldHandleNoFoundPathsCorrectly()
1002 {
1003 long[] nodes = createMoreComplexGraph();
1004 serialize( actions.findSinglePath( nodes[ 0 ], nodes[ 1 ], map( "max depth", 2,
1005 "algorithm", "shortestPath", "relationships", map( "type", "to",
1006 "direction", "in" ), "single", false ) ) );
1007 }
1008
1009 private void assertPaths( int numPaths, long[] nodes, int length, List<Object> result )
1010 {
1011 assertEquals( numPaths, result.size() );
1012 for ( Object path : result )
1013 {
1014 Map<String, Object> serialized = (Map<String, Object>)path;
1015 assertTrue( serialized.get( "start" ).toString().endsWith( "/" + nodes[ 0 ] ) );
1016 assertTrue( serialized.get( "end" ).toString().endsWith( "/" + nodes[ 1 ] ) );
1017 assertEquals( length, serialized.get( "length" ) );
1018 }
1019 }
1020 }