Skip to content

Required vs Optional Relationships

Drivine distinguishes between required (non-nullable) and optional (nullable) relationships in @GraphView classes.

When a relationship property is nullable, Drivine returns all root nodes, even those without the relationship:

@GraphView
data class GuideUserWithOptionalWebUser(
@Root val core: GuideUser,
@GraphRelationship(type = "IS_WEB_USER", direction = Direction.OUTGOING)
val webUser: WebUser? // Nullable - relationship is optional
)
// Returns ALL GuideUsers, even those without a WebUser
val results = graphObjectManager.loadAll<GuideUserWithOptionalWebUser> { }
results.forEach { guide ->
if (guide.webUser != null) {
println("Has web user: ${guide.webUser.displayName}")
} else {
println("No web user")
}
}

When a relationship property is non-nullable, Drivine automatically filters out root nodes that don’t have the relationship:

@GraphView
data class GuideUserWithRequiredWebUser(
@Root val core: GuideUser,
@GraphRelationship(type = "IS_WEB_USER", direction = Direction.OUTGOING)
val webUser: WebUser // Non-nullable - relationship is required!
)
// Only returns GuideUsers that HAVE a WebUser
val results = graphObjectManager.loadAll<GuideUserWithRequiredWebUser> { }
// All results guaranteed to have webUser != null

The generated Cypher includes a WHERE EXISTS clause:

MATCH (core:GuideUser)
WHERE EXISTS { (core)-[:IS_WEB_USER]->(:WebUser) } -- Filters out nodes without relationship
WITH core, ...
RETURN { ... }

This prevents MissingKotlinParameterException that would occur if a null value was deserialized into a non-nullable property.

Property Type Behavior Use Case
val webUser: WebUser? Returns all root nodes Optional relationship, handle null in code
val webUser: WebUser Filters to only nodes with relationship Required relationship, guaranteed non-null
val webUsers: List<WebUser> Returns all root nodes (empty list if none) Collection relationships are always safe