[Neo4j] Spring Data Graph / Neo4j – Problems with OO Inheritance & Polymorphism relation semantics

Michael Hunger michael.hunger at neotechnology.com
Wed Oct 26 19:14:33 CEST 2011


Angelos, I'm currently at SpringOne and quite swamped, I get back to you as soon as possible.

Michael

Am 26.10.2011 um 04:30 schrieb Agelos Pikoulas:

> On my previous email please excuse my confusing Person, the example should
> clearly be like this :
> 
> *
> *
> 
> *@NodeEntity public class Content {}*
> * *
> 
> *@NodeEntity public class ExtContent extends Content {}*
> 
> *@NodeEntity
> public class Person  {
> 
>    @RelatedToVia(elementClass = Person.class, type = "LIKES", direction =
> Direction.OUTGOING)
>    private Set<Person> likedPersons;
>    public Set<Person> getLikedPersons() {return likedPersons;}
> 
>    @RelatedToVia(elementClass = Content.class, type = "LIKES", direction =
> Direction.OUTGOING)
>    private Set<Content> likedContent;
>    public Set<Content> getLikedContent() { return likedContent; }
> }
> 
> *I am attaching the code, if someone can github it cause my eclipse plugin
> refuses to do so :-(*
> *
> On Wed, Oct 26, 2011 at 12:54 AM, Agelos Pikoulas <agelos.pikoulas at gmail.com
>> wrote:
> 
>> Hi to all graphistas,
>> 
>> 
>> I have two issues, a major and a minor :
>> 
>> 1)      1) Starting with SDG 1.0/1.1, I have been developing a MetaModel
>> (and a generator & hopefully later a MetaMetaModel:) and I have been facing
>> walls in regards to @NodeEntity / NodeBacked classes inheritance and their
>> related @RelatedXXX feature set.
>> 
>> To the specifics, when a @NodeEntity class extends another, there is
>> limited support to how these can consistently be related to other nodes
>> (and retrieved) based not just on the RelationShip name, but also on their
>> class (and inheritance/subclass tree).
>> 
>> 
>> To better describe things, look at this simplistic example :
>> 
>> I have
>> 
>>    @NodeEntity public class Content {}
>> 
>>    @NodeEntity public class ExtContent extends Content {}
>> 
>> and
>> 
>> 
>> @NodeEntity public class Person  {
>> 
>>                public Set<Person> getLikedPersons() {return
>> likedPersons;}
>> 
>>                @RelatedToVia(elementClass = Person.class, type = "LIKES",
>> direction = Direction.OUTGOING)
>> 
>>                private Set<Person> likedPersons;
>> 
>> 
>> 
>>                public Iterable<Content> getLikedContent() { return
>> likedContent; }
>> 
>>                @Query ("start n=node({self})  match (n)
>> -[:LIKES]-(content) return content")
>> 
>>                @RelatedToVia(elementClass = Content.class, type =
>> "LIKES", direction = Direction.OUTGOING)
>> 
>>                private Iterable<Content> likedContent;
>> 
>> }
>> 
>> 
>> As you can see, I want Person object/nodes to 'LIKES' other Person objects,
>> or Content objects (and below in the inheritance tree, such as ExtContent) :
>> 
>> 
>> @Test
>>    public void oo_testing() {
>> 
>>        Person p1 = new Person().persist();
>>        Person p2 = new Person().persist();
>>        Content c1 = new Content().persist();
>>        ExtContent c2 = new ExtContent().persist();
>> 
>>        p1.relateTo(c1, "LIKES");
>>        p1.relateTo(c2, "LIKES");
>>        p1.relateTo(p2, "LIKES");
>> 
>>        for (Content cc : p1.getLikedContent())
>>            logger.warn("Class : " + cc.getClass().getName() + ",  __type__
>> : " + cc.getPersistentState().getProperty("__type__"));
>> 
>>        assertEquals("LikedContent objects are 2", 2,
>> p1.getLikedContent().size()); // fails, cause it returns all of 'LIKES'
>> related nodes
>> 
>>    }
>> 
>> 
>> In version 1.1.RELEASE, retrieving any of the collections fails at rutime
>> (can't recall the Exception, but it was the sort of "wrong class found").
>> 
>> 
>> In version 2.0.0.M1 & today's 2.0.0.BUILD-SNAPSHOT, getLikedPersons() &
>> getLikedContent() both contain
>> 
>> ALL nodes that are related via 'LIKES' relationship, irrespective of class.
>> 
>> 
>> 
>> So, this is what p1.getLikedContent() contains :
>> 
>> 
>> Class : sdnTests.domain.Content,  __type__ : sdnTests.domain.Person
>> Class : sdnTests.domain.Content,  __type__ : sdnTests.domain.Content
>> Class : sdnTests.domain.ExtContent,  __type__ : sdnTests.domain.ExtContent
>> 
>> 
>> One would expect that since elementClass defines the class of nodes to
>> fill the collection with, this it would be obeyed.
>> 
>> To a better extend, Iterable<Content> likedContent should contain all
>> object/nodes of type Content AND Content subclasses (eg ExtContent),
>> 
>> since do we have this type information.
>> 
>> 
>> The same lacking of OO/polymorphism exists with repositories,
>> 
>> as discussed here
>> http://lists.neo4j.org/pipermail/user/2011-October/012654.html (haven’t
>> tested this with 2.0.0.M01, I m still on 1.1)
>> 
>> 
>> One can overcome these problems by hand & on top of SDN, but I guess it
>> wouldn't be very elegant & efficient - I think SDN should inherently allow
>> these OO/polymorphic features and emerge itself as a lean & robust OO +
>> Graph repository.
>> 
>> 2)      2) The minor issue I have regards (the otherwise brilliant)
>> @Query, due to its constraint of annotating (mainly) Iterable and NOT
>> allowing Set, List etc (a runtime exception is thrown
>> org.springframework.data.neo4j.conversion.QueryResultBuilder$1 cannot be
>> cast to java.util.List).
>> 
>> This wouldn’t be a huge problem, but the JSP/JSLT <forEach> tag DOESNOT
>> iterate Iterable (!!!), nor you can directly call .iterator() from within
>> JSP, making life hard on both ends.
>> 
>> Regards
>> 
> _______________________________________________
> Neo4j mailing list
> User at lists.neo4j.org
> https://lists.neo4j.org/mailman/listinfo/user



More information about the User mailing list