cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

Array of relationship entities not populating with zero sized array

I have an entity with an array of rich relationships, like this:

@NodeEntity
public class User {

    @Transient
    private static final Logger log = LoggerFactory.getLogger(User.class);

    @Id @GeneratedValue Long id;

    @Relationship(type = "PLAYED")
    public ArrayList<PlayRecord> played_josekis;
 
    //...

I am finding that any query I do to load these User entities gets played_josekis as null if the User has no such relationships.

I have tried the built in findUserById, and I have also tried a query like:

@Query("MATCH (u:User {user_id:{userId}})" +
		"WITH u OPTIONAL MATCH (u) -[r:PLAYED]- (b:BoardPosition) " +
		"RETURN u,r,b")
User loadUserWithPlayRecordByUserId(@Param("userId") Long user_id);

In the latter case, if the User has such a relationship, then the array is populated, but if they do not then it is null instead of a zero sized array.

This seems reasonably painful - it means a check for null of this thing whenever a User is fetched, and adding an empty array when that's the case.

Am I missing something?

6 REPLIES 6

Jiropole
Graph Voyager

As far as I know, this is by design. The OGM has no contract to give you a zero-sized array in lieu of null. You could try assigning a zero-sized array in the constructor, as OGM sets values later in the object lifecycle, and I suspect it does not actually assign a null value.

Thanks for your quick answer!

At a meta level, I have to say "how does that make any sense"? If an entity has an array representing its relationships, how is it "helpful", or in what sense is it "natural" that returning "null" for "this entity definitely has no relationships"?

In fact, overall this one type of issue has been the single thing vexing my whole Neo project: trying to know/understand and ensure that my entities come back properly populated from queries.

But - if we take it as granted, then I think I can't do it in the constructor, because as I understand it I am obliged to have an empty constructor for OGM to use, aren't I? My entities all have this, because that's what I understood is required:

    public User() {
        // Empty constructor required as of Neo4j API 2.0.5
    };

This kind of thing has lead to me starting to have "shims" between the Neo repository classes and the controllers that use them, where the manipulation to correctly populate the entities that get partially returned from Neo in various circumstances gets "fixed" so the controller doesn't have to be forever worrying whether the relationships are populated. It feels "wrong", so I'd love some insight on how this is intended or normally managed!

That's actually quite a standard approach, and exactly what I do. I have a view model for every entity model, and a converter class for converting between. This is so I can normalize or de-normalize for e.g. API request/response.

This is an interesting discussion. I struggled with this a bit, too. My solution was to initialize collections in the constructor and I don't think it's been a problem or causing a slowdown.

public User () {
     this.played_josekis = new ArrayList();
}

Thanks for sharing that.

Somewhere along the lines I got the idea that I have to have an empty constructor, and that this is what Neo uses for constructing query response objects.

Is this simply mistaken on my part?

There needs to be a constructor that takes no arguments, but the constructor itself seems to not need to be empty, so long as any exceptions are checked (or values return null).

Actually, here it is in the documentation. A no-argument constructor is the only requirement.
https://neo4j.com/docs/ogm-manual/current/tutorial/#tutorial:annotations:noarg-constructor