1
votes

I'm modeling my first Spring Data Neo4j app and am wondering about subclassing @RelationshipEntity classes- 1) can it be done, and 2) is it a good idea?

Here's an example of what I'm thinking of using RSS.

A Feed has many Entrys and there are 3 types of entry:

  1. Original entry (new content)
  2. Reblogged content
  3. Liked content (effectively a degenerate Reblog)

A Feed could look like this: @Relationship List<Entry> entries; where Liked is a subclass of Reblog which is a subclass of Entry.

This seems more natural given RelationshipEntities are first class objects: @Relationship(type="Content", Relationship.OUTGOING) List<Entry> entries; ... @RelationshipEntity(type="Content") public class Content { ... @RelationshipEntity(type="RebloggedContent") public class RebloggedContent extends Content { ... @RelationshipEntity(type="LikedContent") public class LikedContent extends Content { ... As I said, this is my first Neo4j app so I don't know if any of these ideas are any good.

From a query point of view I want to be ask questions about both particular types (or combinations of types) of Entry and Entrys as a whole.

Pointers to design/modeling ideas are appreciated.

1

1 Answers

2
votes

It is possible to sub-class relationship entities with the following caveat:

  • Each sub-classed relationship entity must declare an additional distinguishing property that sets it apart from the base class - this information is used by the OGM tool for type introspection.

Example:

Here's an example (in the Kotlin JVM language) of a base relationship entity:

abstract class Relationship
{
    @GraphId
    internal var graphId: Long?
        private set

    @StartNode
    var auditioner: CandidateProfile

    @EndNode
    var auditionee: CandidateProfile

    var createdDate: Date

    init
    {
        this.graphId = null
        this.auditioner = CandidateProfile()
        this.auditionee = CandidateProfile()
        this.createdDate = Date()
    }

    abstract fun mutualRelationship(): Relationship?


}

Along with a sub-class:

@RelationshipEntity(type = "MAYBE_LATER")
class MaybeLater constructor(auditioner: CandidateProfile,
                             auditionee: CandidateProfile,
                             timeOut: Date?) : Relationship()
{
    var timeOut: Date?
    var count: Int

    init
    {
        this.auditioner = auditioner
        this.auditionee = auditionee
        this.timeOut = timeOut
        this.count = 1
    }

    //Provide default constructor for OGM
    constructor() : this(CandidateProfile(), CandidateProfile(), null)


    override fun mutualRelationship(): MaybeLater?
    {
        return auditionee.maybeLaters.find { it.auditionee == auditioner }
    }
}

Usage:

class CandidateProfile {

    @Relationship(type = "LIKES", direction = Relationship.OUTGOING)
    var likes: MutableSet<Like>

    @Relationship(type = "DISLIKES", direction = Relationship.OUTGOING)
    var dislikes: MutableSet<Dislike>

    @Relationship(type = "MAYBE_LATER", direction = Relationship.OUTGOING)
    var maybeLaters: MutableSet<MaybeLater>
}

Note that we define a collection for each separate relationship type. If a single aggregated collection is required, this needs to be done in code.

Neo4j Users Slack Channel:

In addition to StackOverflow, the Neo4j community provides support via the Neo4j Users public Slack channel - joining is highly encouraged.