or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mddatabase-management.mdevents.mdgraph-database.mdgraph-model.mdindex.mdprocedures.mdquery-execution.mdschema.mdspatial.mdtraversal.md

traversal.mddocs/

0

# Traversal and Path Finding

1

2

Graph traversal framework providing programmatic path finding, relationship filtering, and bidirectional traversal with customizable evaluation criteria and path expansion strategies for exploring graph structures.

3

4

## Capabilities

5

6

### Traversal Description

7

8

Interface for describing how to perform graph traversals with configurable evaluation rules and relationship filtering.

9

10

```java { .api }

11

/**

12

* Describes how to perform graph traversals

13

*/

14

public interface TraversalDescription {

15

16

/**

17

* Specify which relationships to follow during traversal

18

* @param relationshipType Type of relationships to follow

19

* @return Modified traversal description

20

*/

21

TraversalDescription relationships(RelationshipType relationshipType);

22

23

/**

24

* Specify relationships and direction to follow

25

* @param relationshipType Type of relationships to follow

26

* @param direction Direction to traverse relationships

27

* @return Modified traversal description

28

*/

29

TraversalDescription relationships(RelationshipType relationshipType, Direction direction);

30

31

/**

32

* Use depth-first traversal strategy

33

* @return Modified traversal description

34

*/

35

TraversalDescription depthFirst();

36

37

/**

38

* Use breadth-first traversal strategy

39

* @return Modified traversal description

40

*/

41

TraversalDescription breadthFirst();

42

43

/**

44

* Set the maximum depth for traversal

45

* @param depth Maximum depth to traverse

46

* @return Modified traversal description

47

*/

48

TraversalDescription evaluator(Evaluator evaluator);

49

50

/**

51

* Set path evaluator to control traversal behavior

52

* @param evaluator Path evaluator

53

* @return Modified traversal description

54

*/

55

TraversalDescription evaluator(PathEvaluator<Path> evaluator);

56

57

/**

58

* Set the path expander for relationship traversal

59

* @param expander Path expander

60

* @return Modified traversal description

61

*/

62

TraversalDescription expand(PathExpander<Path> expander);

63

64

/**

65

* Set uniqueness strategy for nodes and relationships

66

* @param uniqueness Uniqueness strategy

67

* @return Modified traversal description

68

*/

69

TraversalDescription uniqueness(Uniqueness uniqueness);

70

71

/**

72

* Start traversal from the specified node

73

* @param startNode Starting node for traversal

74

* @return Traverser for executing the traversal

75

*/

76

Traverser traverse(Node startNode);

77

78

/**

79

* Start traversal from multiple starting nodes

80

* @param startNodes Starting nodes for traversal

81

* @return Traverser for executing the traversal

82

*/

83

Traverser traverse(Node... startNodes);

84

}

85

```

86

87

**Usage Examples:**

88

89

```java

90

import org.neo4j.graphdb.traversal.*;

91

import org.neo4j.graphdb.Direction;

92

import static org.neo4j.graphdb.traversal.Evaluators.*;

93

94

try (Transaction tx = graphDb.beginTx()) {

95

Node startNode = tx.findNode(Label.label("Person"), "name", "Alice");

96

97

// Simple depth-first traversal

98

TraversalDescription td = tx.traversalDescription()

99

.depthFirst()

100

.relationships(RelationshipType.withName("FRIENDS"), Direction.OUTGOING)

101

.evaluator(toDepth(3));

102

103

for (Path path : td.traverse(startNode)) {

104

Node endNode = path.endNode();

105

System.out.println("Found friend: " + endNode.getProperty("name") +

106

" at depth " + path.length());

107

}

108

109

// Breadth-first traversal with multiple relationship types

110

TraversalDescription td2 = tx.traversalDescription()

111

.breadthFirst()

112

.relationships(RelationshipType.withName("FRIENDS"))

113

.relationships(RelationshipType.withName("COLLEAGUES"))

114

.evaluator(toDepth(2))

115

.uniqueness(Uniqueness.NODE_GLOBAL);

116

117

for (Node node : td2.traverse(startNode).nodes()) {

118

System.out.println("Connected person: " + node.getProperty("name"));

119

}

120

121

tx.commit();

122

}

123

```

124

125

### Traverser Interface

126

127

Interface for executing graph traversals and accessing traversal results.

128

129

```java { .api }

130

/**

131

* Executes graph traversals

132

*/

133

public interface Traverser extends Iterable<Path> {

134

135

/**

136

* Get all nodes found during traversal

137

* @return Iterable of nodes

138

*/

139

Iterable<Node> nodes();

140

141

/**

142

* Get all relationships traversed during traversal

143

* @return Iterable of relationships

144

*/

145

Iterable<Relationship> relationships();

146

147

/**

148

* Get all paths found during traversal

149

* @return Iterable of paths (same as iterator())

150

*/

151

Iterable<Path> paths();

152

153

/**

154

* Get iterator over paths

155

* @return Iterator over paths

156

*/

157

@Override

158

Iterator<Path> iterator();

159

}

160

```

161

162

### Path Evaluators

163

164

Interfaces and implementations for controlling traversal behavior and filtering paths.

165

166

```java { .api }

167

/**

168

* Evaluates paths during traversal to control continuation and inclusion

169

*/

170

public interface PathEvaluator<T> {

171

172

/**

173

* Evaluate a path and return evaluation result

174

* @param path Path to evaluate

175

* @return Evaluation result

176

*/

177

Evaluation evaluate(Path path);

178

}

179

180

/**

181

* Simple evaluator interface for backward compatibility

182

*/

183

public interface Evaluator extends PathEvaluator<Path> {

184

/**

185

* Evaluate a path

186

* @param path Path to evaluate

187

* @return Evaluation result

188

*/

189

@Override

190

Evaluation evaluate(Path path);

191

}

192

193

/**

194

* Evaluation result indicating whether to include path and continue traversal

195

*/

196

public enum Evaluation {

197

/** Include this path in results and continue traversal */

198

INCLUDE_AND_CONTINUE,

199

200

/** Include this path in results but don't continue traversal */

201

INCLUDE_AND_PRUNE,

202

203

/** Don't include this path but continue traversal */

204

EXCLUDE_AND_CONTINUE,

205

206

/** Don't include this path and don't continue traversal */

207

EXCLUDE_AND_PRUNE

208

}

209

```

210

211

**Usage Examples:**

212

213

```java

214

// Custom path evaluator

215

PathEvaluator<Path> customEvaluator = new PathEvaluator<Path>() {

216

@Override

217

public Evaluation evaluate(Path path) {

218

Node endNode = path.endNode();

219

220

// Only include paths ending at Person nodes

221

if (!endNode.hasLabel(Label.label("Person"))) {

222

return Evaluation.EXCLUDE_AND_CONTINUE;

223

}

224

225

// Stop at depth 4

226

if (path.length() >= 4) {

227

return Evaluation.INCLUDE_AND_PRUNE;

228

}

229

230

// Include young people and continue

231

Integer age = (Integer) endNode.getProperty("age", 0);

232

if (age < 30) {

233

return Evaluation.INCLUDE_AND_CONTINUE;

234

}

235

236

// Exclude older people but continue traversal

237

return Evaluation.EXCLUDE_AND_CONTINUE;

238

}

239

};

240

241

// Use custom evaluator

242

TraversalDescription td = tx.traversalDescription()

243

.breadthFirst()

244

.relationships(RelationshipType.withName("KNOWS"))

245

.evaluator(customEvaluator);

246

247

for (Path path : td.traverse(startNode)) {

248

Node person = path.endNode();

249

System.out.println("Young person found: " + person.getProperty("name"));

250

}

251

```

252

253

### Built-in Evaluators

254

255

Factory class providing common path evaluators for typical traversal scenarios.

256

257

```java { .api }

258

/**

259

* Factory for common path evaluators

260

*/

261

public final class Evaluators {

262

263

/**

264

* Evaluator that includes all paths up to a maximum depth

265

* @param depth Maximum depth to traverse

266

* @return Path evaluator

267

*/

268

public static PathEvaluator<Path> toDepth(int depth);

269

270

/**

271

* Evaluator that includes paths from a minimum depth

272

* @param depth Minimum depth to include

273

* @return Path evaluator

274

*/

275

public static PathEvaluator<Path> fromDepth(int depth);

276

277

/**

278

* Evaluator that includes paths within a depth range

279

* @param minDepth Minimum depth (inclusive)

280

* @param maxDepth Maximum depth (inclusive)

281

* @return Path evaluator

282

*/

283

public static PathEvaluator<Path> includingDepths(int minDepth, int maxDepth);

284

285

/**

286

* Evaluator that excludes start node from results

287

* @return Path evaluator

288

*/

289

public static PathEvaluator<Path> excludeStartPosition();

290

291

/**

292

* Evaluator that includes all paths

293

* @return Path evaluator

294

*/

295

public static PathEvaluator<Path> all();

296

297

/**

298

* Evaluator that returns at specific depth only

299

* @param depth Exact depth to return

300

* @return Path evaluator

301

*/

302

public static PathEvaluator<Path> atDepth(int depth);

303

}

304

```

305

306

### Path Expanders

307

308

Interfaces and implementations for controlling how relationships are expanded during traversal.

309

310

```java { .api }

311

/**

312

* Controls how relationships are expanded during traversal

313

*/

314

public interface PathExpander<STATE> {

315

316

/**

317

* Expand from a path to get next relationships

318

* @param path Current path

319

* @return Iterable of relationships to explore

320

*/

321

Iterable<Relationship> expand(Path path, BranchState<STATE> state);

322

323

/**

324

* Reverse this path expander

325

* @return Reversed path expander

326

*/

327

PathExpander<STATE> reverse();

328

}

329

330

/**

331

* Factory for common path expanders

332

*/

333

public final class PathExpanders {

334

335

/**

336

* Create expander for all relationships

337

* @return Path expander

338

*/

339

public static PathExpander<Path> allTypesAndDirections();

340

341

/**

342

* Create expander for specific relationship types and directions

343

* @param types Array of relationship types and directions

344

* @return Path expander

345

*/

346

public static PathExpander<Path> forTypesAndDirections(RelationshipType... types);

347

348

/**

349

* Create expander for outgoing relationships of specific types

350

* @param types Relationship types

351

* @return Path expander

352

*/

353

public static PathExpander<Path> forTypeAndDirection(RelationshipType type, Direction direction);

354

355

/**

356

* Create expander that filters by relationship properties

357

* @param baseExpander Base expander to filter

358

* @param filter Property filter

359

* @return Filtered path expander

360

*/

361

public static PathExpander<Path> forConstantDirectionWithTypes(

362

Direction direction, RelationshipType... types);

363

}

364

```

365

366

### Bidirectional Traversal

367

368

Interface for bidirectional traversal providing collision detection and optimized path finding.

369

370

```java { .api }

371

/**

372

* Bidirectional traversal configuration

373

*/

374

public interface BidirectionalTraversalDescription {

375

376

/**

377

* Set the start side traversal description

378

* @param startSide Traversal description for start side

379

* @return Modified bidirectional traversal description

380

*/

381

BidirectionalTraversalDescription startSide(TraversalDescription startSide);

382

383

/**

384

* Set the end side traversal description

385

* @param endSide Traversal description for end side

386

* @return Modified bidirectional traversal description

387

*/

388

BidirectionalTraversalDescription endSide(TraversalDescription endSide);

389

390

/**

391

* Set collision evaluator for detecting path intersections

392

* @param collisionEvaluator Collision evaluator

393

* @return Modified bidirectional traversal description

394

*/

395

BidirectionalTraversalDescription collisionEvaluator(

396

PathEvaluator<Path> collisionEvaluator);

397

398

/**

399

* Set side selector for controlling alternation between sides

400

* @param sideSelector Side selector

401

* @return Modified bidirectional traversal description

402

*/

403

BidirectionalTraversalDescription sideSelector(SideSelector sideSelector);

404

405

/**

406

* Find paths between start and end nodes

407

* @param start Start node

408

* @param end End node

409

* @return Iterable of paths found

410

*/

411

Iterable<Path> traverse(Node start, Node end);

412

}

413

```

414

415

**Advanced Traversal Examples:**

416

417

```java

418

// Complex traversal with multiple constraints

419

try (Transaction tx = graphDb.beginTx()) {

420

Node alice = tx.findNode(Label.label("Person"), "name", "Alice");

421

422

// Find all reachable people within 3 hops, excluding blocked relationships

423

PathExpander<Path> expander = new PathExpander<Path>() {

424

@Override

425

public Iterable<Relationship> expand(Path path, BranchState<Path> state) {

426

List<Relationship> validRels = new ArrayList<>();

427

428

for (Relationship rel : path.endNode().getRelationships(Direction.OUTGOING)) {

429

// Skip blocked relationships

430

if (!rel.hasProperty("blocked")) {

431

// Only follow certain relationship types

432

if (rel.isType(RelationshipType.withName("FRIENDS")) ||

433

rel.isType(RelationshipType.withName("COLLEAGUES"))) {

434

validRels.add(rel);

435

}

436

}

437

}

438

439

return validRels;

440

}

441

442

@Override

443

public PathExpander<Path> reverse() {

444

return this; // Simplified for example

445

}

446

};

447

448

TraversalDescription td = tx.traversalDescription()

449

.breadthFirst()

450

.expand(expander)

451

.evaluator(Evaluators.toDepth(3))

452

.evaluator(Evaluators.excludeStartPosition())

453

.uniqueness(Uniqueness.NODE_GLOBAL);

454

455

System.out.println("People reachable from Alice:");

456

for (Node person : td.traverse(alice).nodes()) {

457

System.out.println(" " + person.getProperty("name"));

458

}

459

460

tx.commit();

461

}

462

463

// Bidirectional traversal for shortest path

464

try (Transaction tx = graphDb.beginTx()) {

465

Node start = tx.findNode(Label.label("Person"), "name", "Alice");

466

Node end = tx.findNode(Label.label("Person"), "name", "Bob");

467

468

TraversalDescription forwardTraversal = tx.traversalDescription()

469

.breadthFirst()

470

.relationships(RelationshipType.withName("KNOWS"), Direction.OUTGOING);

471

472

TraversalDescription backwardTraversal = tx.traversalDescription()

473

.breadthFirst()

474

.relationships(RelationshipType.withName("KNOWS"), Direction.INCOMING);

475

476

BidirectionalTraversalDescription bidirectional = tx.bidirectionalTraversalDescription()

477

.startSide(forwardTraversal)

478

.endSide(backwardTraversal)

479

.collisionEvaluator(Evaluators.all());

480

481

for (Path path : bidirectional.traverse(start, end)) {

482

System.out.println("Found path of length " + path.length());

483

for (Node node : path.nodes()) {

484

System.out.println(" " + node.getProperty("name"));

485

}

486

break; // Just get the first (shortest) path

487

}

488

489

tx.commit();

490

}

491

492

// Traversal with stateful path expander

493

public class StatefulExpander implements PathExpander<Integer> {

494

private final int maxBudget;

495

496

public StatefulExpander(int maxBudget) {

497

this.maxBudget = maxBudget;

498

}

499

500

@Override

501

public Iterable<Relationship> expand(Path path, BranchState<Integer> state) {

502

Integer remainingBudget = state.getState();

503

if (remainingBudget == null) {

504

remainingBudget = maxBudget;

505

}

506

507

List<Relationship> affordable = new ArrayList<>();

508

509

for (Relationship rel : path.endNode().getRelationships()) {

510

Integer cost = (Integer) rel.getProperty("cost", 1);

511

if (cost <= remainingBudget) {

512

affordable.add(rel);

513

// Set remaining budget for next level

514

state.setState(remainingBudget - cost);

515

}

516

}

517

518

return affordable;

519

}

520

521

@Override

522

public PathExpander<Integer> reverse() {

523

return new StatefulExpander(maxBudget);

524

}

525

}

526

527

// Use stateful expander

528

TraversalDescription costAwareTraversal = tx.traversalDescription()

529

.breadthFirst()

530

.expand(new StatefulExpander(10))

531

.evaluator(Evaluators.toDepth(5));

532

533

for (Path path : costAwareTraversal.traverse(startNode)) {

534

System.out.println("Found affordable path: " + path.length() + " hops");

535

}

536

```